mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
feat(pair-corpus-honesty): add vibe-py, vfc-js and agent-vfc slices with mechanism vocabulary
Tasks 1.1, 5.1, 5.2, 5.4 and the data half of 5.3. - mechanisms.toml: closed vocabulary v1 (20 ids) every expected row cites. - vibe-py: 35 Real-Vuln-Benchmark pairs (Apache-2.0), human provenance only because the LLM-generated repositories carry no license (escalated). - vfc-js: 17 Node fix-commit pairs harvested upstream (MIT/Apache-2.0), SecBench.js itself is not vendored (no license); sinks derived on 13/17. - agent-vfc: 29 agent-trailer fixes as catalog-candidates.toml plus REVIEW.md; the loaded catalog stays empty until a human reviews them. - datasets.toml and README document every slice and its review status. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
c3e841003c
commit
8ab4207618
@@ -40,6 +40,41 @@ Pairs in this directory **must not** join `LANGUAGE_MANIFESTS`.
|
||||
`vfc/training/manifest.jsonl` (vuln vs fixed, one snapshot per line).
|
||||
Grow with a blobless `git log --grep=CVE-202` mine plus `vfc/harvest.py`,
|
||||
then `vfc/generate_catalog.py` (maintainer, not CI).
|
||||
- **vibe-py** — Real-Vuln-Benchmark functions (`benchmarks/pairs/vibe-py/`):
|
||||
Python web repos pinned by commit, one vulnerable function per pair with a
|
||||
false-positive trap from the same repo as the fixed twin. Today only the 15
|
||||
licensed human-authored repos are vendored (`provenance = "human"`); the 40
|
||||
LLM-generated repos carry no license file and are excluded until one is
|
||||
stated upstream. Educational/CTF apps, not production. Honesty dashboard.
|
||||
- **vfc-js** — server-side JavaScript function pairs harvested from the upstream
|
||||
fix commits that SecBench.js records (`benchmarks/pairs/vfc-js/`). Command
|
||||
injection, path traversal, and code injection first; prototype pollution and
|
||||
ReDoS carry their mechanism and may be `known_limit`. No SecBench.js file is
|
||||
vendored. Honesty dashboard.
|
||||
- **agent-vfc** — security-fix commits carrying an AI agent co-author trailer or
|
||||
generation marker, in JavaScript, TypeScript, or Python
|
||||
(`benchmarks/pairs/agent-vfc/`). `provenance = "agent"`. Rows enter
|
||||
`catalog.toml` only after a human sets `reviewer` in `recipes.toml`; until
|
||||
then they sit in `catalog-candidates.toml`, which is never loaded. Honesty dashboard.
|
||||
|
||||
## Labels, profiles, and mechanisms
|
||||
|
||||
Every `[[pair.expected]]` row names a `mechanism` from the closed vocabulary in
|
||||
`benchmarks/pairs/mechanisms.toml`; every pair carries `provenance`
|
||||
(`human|agent|mixed|synthetic`), a declared `split` (`train|holdout`), and an
|
||||
optional `known_limit` reason. The scorer counts overlay `coverage` records with
|
||||
a source as detections and as leaks, matches by function when a label names one,
|
||||
never matches a CWE-only row (`weak_label`), and reports `per_profile`,
|
||||
`per_mechanism`, `achievable` (known-limit pairs excluded), and `loss`
|
||||
(parse-failed files, unadjudicated proposals). `ousast pairs --profile agent
|
||||
--split holdout --json` filters; `--hunter` adds the LLM hunter as a third scorer
|
||||
when a hunter model is configured. The improve loop rejects a change that
|
||||
regresses any profile on the holdout split.
|
||||
|
||||
Harvest for every slice goes through `benchmarks/pairs/harvest.py --slice <name>`
|
||||
(modes `name`, `line_range`, `hunk`, `enclosing`; comment and string mentions
|
||||
never anchor) and `benchmarks/pairs/catalog_gen.py --slice <name>` regenerates
|
||||
the catalog from `recipes.toml`. Maintainer only; CI never fetches.
|
||||
|
||||
## Commands
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# agent-vfc slice
|
||||
|
||||
Security-fix commits carrying an AI coding agent co-author trailer or generation marker
|
||||
(Claude Code, Codex, Cursor, Copilot, Devin), in JavaScript, TypeScript, or Python.
|
||||
`provenance = "agent"`. Only repositories with a stated license are vendored.
|
||||
|
||||
## Review checklist (Req 5.3)
|
||||
|
||||
A recipe with `reviewer = "pending"` is a candidate, not a label. Before setting `reviewer`:
|
||||
|
||||
1. The parent excerpt really contains the vulnerability the title claims (not a refactor).
|
||||
2. One mechanism from `benchmarks/pairs/mechanisms.toml` explains it; adjust `mechanism` and `cwe`.
|
||||
3. The fixed excerpt removes it and the change is inside the vendored function.
|
||||
4. No secret, token, or personal data is in either excerpt (run the redaction check).
|
||||
5. The license header is present and matches the repository license.
|
||||
|
||||
Rebuild: `python benchmarks/pairs/agent-vfc/build_recipes.py --search /tmp/agents.jsonl` then
|
||||
`--from /tmp/agents.jsonl`, `harvest.py --slice agent-vfc --all --fetch`, `catalog_gen.py --slice agent-vfc`.
|
||||
@@ -0,0 +1,45 @@
|
||||
# agent-vfc candidate review sheet
|
||||
|
||||
Set `reviewer = "<name>"` in `recipes.toml` for each row you confirm (and fix `mechanism`/`cwe` if the title-based guess is wrong), then run `python benchmarks/pairs/catalog_gen.py --slice agent-vfc`. Rows without a reviewer stay in `catalog-candidates.toml` and are never scored.
|
||||
|
||||
| # | name | mechanism (guess) | cwe | language | commit | title |
|
||||
|---|------|-------------------|-----|----------|--------|-------|
|
||||
| 1 | `academic-based-qoder-app-a79ddb` | permissive_default | CWE-16 | python | [a79ddb90](https://github.com/1173591564/academic-based-qoder/commit/a79ddb90def54e91f7507cbf6b1548b224d642aa) | fix(hub): allow DSH token validation CORS |
|
||||
| 2 | `anastasios-pw-session-14ec1a` | source_reaches_sink | CWE-918 | typescript | [14ec1ac5](https://github.com/Anas329796/Anastasios/commit/14ec1ac50f9e4e255d875236d30129c6207401d4) | fix(browser): harden SSRF redirect guard against non-navigation document hops [A |
|
||||
| 3 | `arsnova-eu-httpcors-9bcba4` | permissive_default | CWE-16 | typescript | [9bcba4f4](https://github.com/kqc-real/arsnova.eu/commit/9bcba4f442aecc6a5e16ef2dc6115177cfc2b6df) | fix(security): Produktions-CORS auf Same-Origin begrenzen (#143) |
|
||||
| 4 | `astroclaw-pw-session-1553a8` | source_reaches_sink | CWE-918 | typescript | [1553a8ad](https://github.com/P1R4N351/astroclaw/commit/1553a8adf123913cf7f1f1c75be4c4e5cd6c796b) | fix(browser): harden SSRF redirect guard against non-navigation document hops [A |
|
||||
| 5 | `capgo-app-apptabs-7d73fd` | permissive_default | CWE-16 | typescript | [7d73fd21](https://github.com/Cap-go/capgo.app/commit/7d73fd21a59eaa3a4e20c6dc0d280e73e47435b7) | fix(notifications): harden API CORS and mark console tab as beta (#2623) |
|
||||
| 6 | `capgo-app-hono-4dadd2` | permissive_default | CWE-16 | typescript | [4dadd258](https://github.com/Cap-go/capgo.app/commit/4dadd2580d02213d227a331eee0232aa59859b59) | fix(api): CORS for Capacitor localhost WebView (#3105) |
|
||||
| 7 | `dailyforge-server-ed1470` | permissive_default | CWE-16 | javascript | [ed147081](https://github.com/Annamdevula-Nissi-Grace/Dailyforge/commit/ed1470814a108bd725c8b27bd9d86cf95a979a96) | Fix: add localhost fallback for CORS origin (#172) |
|
||||
| 8 | `dnf-plugin-anyrepo-config-26d19a` | path_join_user_input | CWE-22 | python | [26d19aeb](https://github.com/jfut/dnf-plugin-anyrepo/commit/26d19aeb8884f244e34ccfdc4f49f07055adc4d0) | fix(config): prevent path traversal in repository names |
|
||||
| 9 | `edutrace-page-ee7ba2` | prototype_pollution | CWE-1321 | typescript | [ee7ba25f](https://github.com/jardimdesoftware/edutrace/commit/ee7ba25fb23ea89cc1b67549cb5e32c8ead92739) | fix(front): impedir prototype pollution nos handlers de formulário aninhado |
|
||||
| 10 | `etoj-index-605274` | permissive_default | CWE-16 | typescript | [6052743d](https://github.com/Eternity-Sky/_ETOJ/commit/6052743d477eeff62e32553c2790785d3f52c641) | Fix CORS: Add PATCH method to allowed methods |
|
||||
| 11 | `etude-lexical-markdown-editorconfig-c61a8b` | prototype_pollution | CWE-1321 | typescript | [c61a8bf7](https://github.com/dayflower/etude-lexical-markdown/commit/c61a8bf78fe20d6ae0eab2e4b8b02004508525ed) | fix: guard deepMergeInto against prototype pollution |
|
||||
| 12 | `etude-lexical-markdown-editorconfig-db4f54` | prototype_pollution | CWE-1321 | typescript | [db4f54b1](https://github.com/dayflower/etude-lexical-markdown/commit/db4f54b1ab80ad596de6425e84f90aa781c49999) | fix: make prototype pollution guard recognizable by CodeQL |
|
||||
| 13 | `gitim-git-cors-proxy-e4c3a4` | permissive_default | CWE-16 | typescript | [e4c3a479](https://github.com/CiferaTeam/GitIM/commit/e4c3a4794dbe9fbcce679f7df1ecd2b09b40f9d6) | fix(frontend): use gitim cors proxy by default |
|
||||
| 14 | `lensops-kubernetesmanagement-fe4910` | missing_auth_guard | CWE-862 | typescript | [fe49109a](https://github.com/amitknigam84/lensops/commit/fe49109aedfe21dea4d24d4d9f2fa3f1ecfb6c84) | Fix missing auth header on namespaces API call |
|
||||
| 15 | `market-cap-route-4f8ae9` | source_reaches_sink | CWE-601 | typescript | [4f8ae9be](https://github.com/navaneethbv/market-cap/commit/4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6) | Fix open redirects on the auth next param |
|
||||
| 16 | `melodix-playerprovider-089931` | permissive_default | CWE-16 | typescript | [089931ef](https://github.com/alexshao3/melodix/commit/089931ef71ea1e5b7586520baf1a5498e2f05b13) | Merge pull request #17 from alexshao3/devin/1777216143-fix-audio-cors |
|
||||
| 17 | `mercado-do-vale-news-catalogmetadataservice-9b5fcf` | permissive_default | CWE-16 | typescript | [9b5fcf2d](https://github.com/handielson/Mercado-do-vale-news/commit/9b5fcf2dae41e56f5f97952266f2d6ba59598598) | fix(catalog): avoid metadata cors preflight |
|
||||
| 18 | `money-track-category-icons-4d4a5b` | prototype_pollution | CWE-1321 | typescript | [4d4a5b06](https://github.com/andrebubniak/money-track/commit/4d4a5b063278c8b6697c3faae133d7c39fcd01c0) | fix(category-icons): use Object.hasOwn to prevent prototype pollution in type gu |
|
||||
| 19 | `nestjs-filter-normalizer-aa0e60` | prototype_pollution | CWE-1321 | typescript | [aa0e600d](https://github.com/DavideCarvalho/nestjs-filter/commit/aa0e600d05997ea3d77538ea1c2db427c439f2e8) | fix(core): add prototype pollution guard to normalizeInput |
|
||||
| 20 | `new-erp-final-app-6e9644` | permissive_default | CWE-16 | typescript | [6e9644c8](https://github.com/Sachin-Salgar/NEW_ERP_FINAL/commit/6e9644c81ce3fb356669157182a5ef09a70c4b59) | fix: allow patch requests through cors |
|
||||
| 21 | `nimestream-route-d17f53` | source_reaches_sink | CWE-918 | javascript | [d17f535b](https://github.com/Irnhakim/nimestream/commit/d17f535bf3012041b056ff3aa991ff6cfa198e43) | fix: resolve command injection and SSRF/Open Redirect security issues in multiSc |
|
||||
| 22 | `onlook-helper-57ce1c` | missing_auth_guard | CWE-862 | typescript | [57ce1ccf](https://github.com/zhcndoc/onlook/commit/57ce1ccfacc7e8484cae59013a2b1e34518560e5) | Fix CVE-2025-63783: Add authorization checks to project mutation APIs (#3062) |
|
||||
| 23 | `openniw-jobs-0fc947` | identity_from_request_body | CWE-639 | python | [0fc94733](https://github.com/HHHHHejia/openniw/commit/0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10) | Fix IDOR on job endpoint: case-bound jobs require case ownership |
|
||||
| 24 | `openniw-jobs-b74de3` | identity_from_request_body | CWE-639 | python | [b74de31b](https://github.com/ziyuzuo/openniw/commit/b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68) | Fix IDOR on job endpoint: case-bound jobs require case ownership |
|
||||
| 25 | `overleaf-with-claude-exportscontroller-3980b9` | identity_from_request_body | CWE-639 | javascript | [3980b9e5](https://github.com/ZUENS2020/overleaf-with-claude/commit/3980b9e5806defb63e45ae2696e6c1899f3a8431) | Fix IDOR in exports by adding token verification (Issue #31637) (#32883) |
|
||||
| 26 | `popmark-editorconfig-e5ac40` | prototype_pollution | CWE-1321 | typescript | [e5ac407c](https://github.com/dayflower/popmark/commit/e5ac407cef37c37178d440541ede301c838640fb) | fix: guard deepMergeInto against prototype pollution |
|
||||
| 27 | `rag-pipeline-utils-config-handler-76e5f0` | prototype_pollution | CWE-1321 | javascript | [76e5f0a9](https://github.com/DevilsDev/rag-pipeline-utils/commit/76e5f0a94d6803d0e463d26a61cedb7da90857a7) | fix(security): prevent prototype pollution in config-handler |
|
||||
| 28 | `registry-proxy-worker-426847` | permissive_default | CWE-16 | javascript | [42684789](https://github.com/agents-repo/registry-proxy/commit/426847899eb2ee94ae4e5a3aacc50423e36d2dc8) | fix: handle CORS OPTIONS preflight for catalog fetches (#10) |
|
||||
| 29 | `rls-alembic-rls-d2b6af` | permissive_default | CWE-16 | python | [d2b6af47](https://github.com/DelfinaCare/rls/commit/d2b6af47347fb285b7a3820a7f2d5dded20907ec) | Guard against ENABLE ROW LEVEL SECURITY on tables with no policies (#143) |
|
||||
| 30 | `supplieradvisor-mvp-route-387bcf` | identity_from_request_body | CWE-639 | typescript | [387bcf40](https://github.com/bigfivefoods/supplieradvisor-mvp/commit/387bcf40e984a2ee1832ab7beabf0284c5b627d8) | Brief 62: Fix IDOR on customer_claims PATCH/DELETE (#156) |
|
||||
| 31 | `supplieradvisor-mvp-route-a69e8f` | identity_from_request_body | CWE-639 | typescript | [a69e8f27](https://github.com/bigfivefoods/supplieradvisor-mvp/commit/a69e8f27c0f4d402573d16f0612b51155bbc46e1) | Brief 60: Fix IDOR on opportunities GET/PATCH/DELETE (missing company membership |
|
||||
| 32 | `tools-cli-tools-a96bc0` | source_reaches_sink | CWE-78 | python | [a96bc050](https://github.com/D-sorganization/Tools/commit/a96bc0502a3dcdac303e4f0152508886e5c35c0a) | 🛡️ Sentinel: [CRITICAL] Fix command injection in ShellTool (#3307) |
|
||||
| 33 | `tools-wsgi-e18686` | path_join_user_input | CWE-22 | python | [e18686aa](https://github.com/D-sorganization/Tools/commit/e18686aaa174a8a4843c07b4727771c92e0f179e) | fix(security): validate mesh filenames against path traversal in _download_meshe |
|
||||
| 34 | `trackly-cli-path-diagnostics-1c1aed` | path_join_user_input | CWE-22 | javascript | [1c1aed89](https://github.com/trackly-app/trackly-cli/commit/1c1aed89b07edb04051830c8f086e02b65e961c6) | fix(apply): report blocked path traversal |
|
||||
| 35 | `upstreamdrift-local-server-c3a078` | path_join_user_input | CWE-22 | python | [c3a07870](https://github.com/D-sorganization/UpstreamDrift/commit/c3a0787080489b30e2ed0abfac03b51e45da184b) | fix(api): harden local server path traversal (#2805) (#2839) |
|
||||
| 36 | `vantalk-firebase-16c3b0` | secret_in_client | CWE-798 | typescript | [16c3b028](https://github.com/NiSeullent/VanTalk/commit/16c3b02875b1f51c3cac1dc185e199978a35985c) | fix(security): load Firebase API key from env, remove hardcoded secret |
|
||||
| 37 | `waggledance-swarm-ssrf-host-guard-9a4548` | source_reaches_sink | CWE-918 | python | [9a454843](https://github.com/Ahkeratmehilaiset/waggledance-swarm/commit/9a454843aa35332ff2eb3106023eee0c4b5e444b) | fix(ssrf): reject bare-string allowed hosts (#1460) |
|
||||
| 38 | `workers-research-utils-209444` | source_reaches_sink | CWE-89 | typescript | [209444eb](https://github.com/G4brym/workers-research/commit/209444eb61cc564c2d6b43267256f85fe3e5e30e) | Fix SQL injection in search by using parameterized queries (#41) |
|
||||
| 39 | `zoonk-origin-bfbf67` | permissive_default | CWE-16 | typescript | [bfbf670c](https://github.com/zoonk/zoonk/commit/bfbf670ccb41d63c407d32c51bd26e626a174f31) | fix(api): allow staging cors from previews (#1559) |
|
||||
@@ -0,0 +1,38 @@
|
||||
// Provenance: Anas329796/Anastasios (fixed).
|
||||
// repo: Anas329796/Anastasios
|
||||
// commit: 14ec1ac50f9e4e255d875236d30129c6207401d4
|
||||
// parent: adb7b0d5d6b81c46d56451c709e7eac9d0dc93fb
|
||||
// commit_url: https://github.com/Anas329796/Anastasios/commit/14ec1ac50f9e4e255d875236d30129c6207401d4
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: isTopLevelNavigationRequest
|
||||
// relpath: extensions/browser/src/browser/pw-session.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
function isTopLevelNavigationRequest(page: Page, request: Request): boolean {
|
||||
let sameMainFrame = false;
|
||||
try {
|
||||
sameMainFrame = request.frame() === page.mainFrame();
|
||||
} catch {
|
||||
// Frame resolution can fail during redirect/renderer churn; fail closed.
|
||||
sameMainFrame = true;
|
||||
}
|
||||
if (!sameMainFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (request.isNavigationRequest()) {
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
// Ignore and fall back to resource-type check below.
|
||||
}
|
||||
|
||||
try {
|
||||
return request.resourceType() === "document";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Provenance: Anas329796/Anastasios (vuln).
|
||||
// repo: Anas329796/Anastasios
|
||||
// commit: adb7b0d5d6b81c46d56451c709e7eac9d0dc93fb
|
||||
// parent: adb7b0d5d6b81c46d56451c709e7eac9d0dc93fb
|
||||
// commit_url: https://github.com/Anas329796/Anastasios/commit/14ec1ac50f9e4e255d875236d30129c6207401d4
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: isTopLevelNavigationRequest
|
||||
// relpath: extensions/browser/src/browser/pw-session.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
function isTopLevelNavigationRequest(page: Page, request: Request): boolean {
|
||||
if (!request.isNavigationRequest()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return request.frame() === page.mainFrame();
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Provenance: P1R4N351/astroclaw (fixed).
|
||||
// repo: P1R4N351/astroclaw
|
||||
// commit: 1553a8adf123913cf7f1f1c75be4c4e5cd6c796b
|
||||
// parent: d3eed2dc01328f21dd404477bb28e2740fa371a4
|
||||
// commit_url: https://github.com/P1R4N351/astroclaw/commit/1553a8adf123913cf7f1f1c75be4c4e5cd6c796b
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: isTopLevelNavigationRequest
|
||||
// relpath: extensions/browser/src/browser/pw-session.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
function isTopLevelNavigationRequest(page: Page, request: Request): boolean {
|
||||
let sameMainFrame = false;
|
||||
try {
|
||||
sameMainFrame = request.frame() === page.mainFrame();
|
||||
} catch {
|
||||
// Frame resolution can fail during redirect/renderer churn; fail closed.
|
||||
sameMainFrame = true;
|
||||
}
|
||||
if (!sameMainFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (request.isNavigationRequest()) {
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
// Ignore and fall back to resource-type check below.
|
||||
}
|
||||
|
||||
try {
|
||||
return request.resourceType() === "document";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Provenance: P1R4N351/astroclaw (vuln).
|
||||
// repo: P1R4N351/astroclaw
|
||||
// commit: d3eed2dc01328f21dd404477bb28e2740fa371a4
|
||||
// parent: d3eed2dc01328f21dd404477bb28e2740fa371a4
|
||||
// commit_url: https://github.com/P1R4N351/astroclaw/commit/1553a8adf123913cf7f1f1c75be4c4e5cd6c796b
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: isTopLevelNavigationRequest
|
||||
// relpath: extensions/browser/src/browser/pw-session.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
function isTopLevelNavigationRequest(page: Page, request: Request): boolean {
|
||||
if (!request.isNavigationRequest()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return request.frame() === page.mainFrame();
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build agent-vfc candidate recipes from agent-authored security-fix commits (maintainer, network via gh).
|
||||
|
||||
Candidates come from GitHub commit search on agent co-author trailers or generation
|
||||
markers plus security-fix wording (see --search). Each candidate is kept only when the
|
||||
repository states a license, the fix touches one to three JavaScript, TypeScript, or
|
||||
Python files, and the largest changed file has at most --max-lines changed lines.
|
||||
Every recipe starts with ``reviewer = "pending"``; a human must set the reviewer and
|
||||
confirm the mechanism before the pair is trusted (Req 5.3).
|
||||
|
||||
python benchmarks/pairs/agent-vfc/build_recipes.py --search /tmp/agent_candidates.jsonl
|
||||
python benchmarks/pairs/agent-vfc/build_recipes.py --from /tmp/agent_candidates.jsonl
|
||||
python benchmarks/pairs/harvest.py --slice agent-vfc --all --fetch
|
||||
python benchmarks/pairs/catalog_gen.py --slice agent-vfc
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
TRAILERS = (
|
||||
'"Co-Authored-By: Claude"',
|
||||
'"Generated with Claude Code"',
|
||||
'"Co-authored-by: Cursor"',
|
||||
'"Co-authored-by: Codex"',
|
||||
'"Co-authored-by: Copilot"',
|
||||
'"Co-authored-by: devin"',
|
||||
)
|
||||
KEYWORDS = (
|
||||
'"fix IDOR"',
|
||||
'"SQL injection"',
|
||||
'"path traversal"',
|
||||
"SSRF",
|
||||
'"hardcoded secret"',
|
||||
'"CORS"',
|
||||
'"row level security"',
|
||||
'"authorization check"',
|
||||
'"command injection"',
|
||||
'"prototype pollution"',
|
||||
'"open redirect"',
|
||||
'"missing authentication"',
|
||||
)
|
||||
MECHANISM_BY_TITLE = (
|
||||
(
|
||||
re.compile(r"\bidor\b|ownership|owner.?scope|user_id from|tenant", re.I),
|
||||
"identity_from_request_body",
|
||||
"CWE-639",
|
||||
"insecure direct object reference",
|
||||
),
|
||||
(
|
||||
re.compile(r"missing auth|unauthenticated|auth(?:orization|entication)? (?:check|guard|middleware)|require.?auth", re.I),
|
||||
"missing_auth_guard",
|
||||
"CWE-862",
|
||||
"missing authorization",
|
||||
),
|
||||
(re.compile(r"sql injection|sqli", re.I), "source_reaches_sink", "CWE-89", "sql injection"),
|
||||
(re.compile(r"path traversal|zip slip|directory traversal", re.I), "path_join_user_input", "CWE-22", "path traversal"),
|
||||
(re.compile(r"\bssrf\b", re.I), "source_reaches_sink", "CWE-918", "server-side request forgery"),
|
||||
(re.compile(r"command injection|shell injection", re.I), "source_reaches_sink", "CWE-78", "command injection"),
|
||||
(re.compile(r"prototype pollution", re.I), "prototype_pollution", "CWE-1321", "prototype pollution"),
|
||||
(re.compile(r"open redirect", re.I), "source_reaches_sink", "CWE-601", "open redirect"),
|
||||
(
|
||||
re.compile(r"hardcoded|hard-coded|leaked (?:key|secret|token)|service.?role", re.I),
|
||||
"secret_in_client",
|
||||
"CWE-798",
|
||||
"hardcoded credentials",
|
||||
),
|
||||
(re.compile(r"\bcors\b|row level security|\brls\b|debug", re.I), "permissive_default", "CWE-16", "permissive default"),
|
||||
)
|
||||
ACCEPTED_LICENSES = {
|
||||
"MIT",
|
||||
"Apache-2.0",
|
||||
"BSD-3-Clause",
|
||||
"BSD-2-Clause",
|
||||
"ISC",
|
||||
"MPL-2.0",
|
||||
"GPL-3.0",
|
||||
"GPL-2.0",
|
||||
"AGPL-3.0",
|
||||
"Unlicense",
|
||||
"0BSD",
|
||||
}
|
||||
_CODE = re.compile(r"\.(py|js|mjs|cjs|ts|tsx)$")
|
||||
_SKIP = re.compile(r"(test|spec|\.d\.ts|migration|dist/|build/|min\.js|\.config\.|stories)", re.I)
|
||||
_NOISE = re.compile(r"\b(css|icon|i18n|layout|docs?|tracker|sess[aã]o|chore|bump|migration|workflow)\b", re.I)
|
||||
|
||||
|
||||
def _gh(args: list[str]) -> object:
|
||||
return json.loads(subprocess.check_output(["gh", "api", *args], stderr=subprocess.DEVNULL))
|
||||
|
||||
|
||||
def search(out: Path) -> int:
|
||||
seen: set[tuple[str, str]] = set()
|
||||
with out.open("w") as handle:
|
||||
for trailer in TRAILERS:
|
||||
for keyword in KEYWORDS:
|
||||
time.sleep(6) # commit search has a strict secondary rate limit
|
||||
try:
|
||||
result = _gh(["-X", "GET", "search/commits", "-f", f"q={trailer} {keyword} fix", "-f", "per_page=30"])
|
||||
except Exception: # noqa: BLE001 — rate limited; keep going
|
||||
continue
|
||||
for item in result.get("items", []) if isinstance(result, dict) else []:
|
||||
key = (item["repository"]["full_name"], item["sha"])
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
handle.write(
|
||||
json.dumps(
|
||||
{
|
||||
"repo": key[0],
|
||||
"sha": key[1],
|
||||
"title": item["commit"]["message"].split("\n")[0][:160],
|
||||
"date": item["commit"]["author"]["date"],
|
||||
}
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
return len(seen)
|
||||
|
||||
|
||||
def classify(title: str) -> tuple[str, str, str] | None:
|
||||
for pattern, mechanism, cwe, cls in MECHANISM_BY_TITLE:
|
||||
if pattern.search(title):
|
||||
return mechanism, cwe, cls
|
||||
return None
|
||||
|
||||
|
||||
def build(source: Path, *, limit: int, max_lines: int) -> tuple[list[dict[str, object]], dict[str, int]]:
|
||||
recipes: list[dict[str, object]] = []
|
||||
skipped = {"noise_title": 0, "unclassified": 0, "unlicensed": 0, "no_code_file": 0, "too_big": 0, "api": 0, "duplicate_repo": 0}
|
||||
per_repo: dict[str, int] = {}
|
||||
seen_commits: set[str] = set() # the same fix commit shows up in every fork
|
||||
rows = [json.loads(line) for line in source.read_text().splitlines() if line.strip()]
|
||||
for row in sorted(rows, key=lambda r: (r["repo"], r["date"])):
|
||||
if len(recipes) >= limit:
|
||||
break
|
||||
title = str(row["title"])
|
||||
if _NOISE.search(title):
|
||||
skipped["noise_title"] += 1
|
||||
continue
|
||||
classified = classify(title)
|
||||
if classified is None:
|
||||
skipped["unclassified"] += 1
|
||||
continue
|
||||
if per_repo.get(row["repo"], 0) >= 2 or row["sha"] in seen_commits:
|
||||
skipped["duplicate_repo"] += 1
|
||||
continue
|
||||
seen_commits.add(row["sha"])
|
||||
time.sleep(0.8)
|
||||
try:
|
||||
info = _gh([f"repos/{row['repo']}"])
|
||||
commit = _gh([f"repos/{row['repo']}/commits/{row['sha']}"])
|
||||
except Exception: # noqa: BLE001
|
||||
skipped["api"] += 1
|
||||
continue
|
||||
assert isinstance(info, dict) and isinstance(commit, dict)
|
||||
license_id = (info.get("license") or {}).get("spdx_id") or ""
|
||||
if license_id not in ACCEPTED_LICENSES:
|
||||
skipped["unlicensed"] += 1
|
||||
continue
|
||||
files = [f for f in commit.get("files", []) if _CODE.search(f["filename"]) and not _SKIP.search(f["filename"]) and f.get("patch")]
|
||||
if not files or len(files) > 3:
|
||||
skipped["no_code_file"] += 1
|
||||
continue
|
||||
target = sorted(files, key=lambda f: -(f.get("additions", 0) + f.get("deletions", 0)))[0]
|
||||
if target.get("additions", 0) + target.get("deletions", 0) > max_lines:
|
||||
skipped["too_big"] += 1
|
||||
continue
|
||||
parents = commit.get("parents") or []
|
||||
if not parents:
|
||||
skipped["api"] += 1
|
||||
continue
|
||||
mechanism, cwe, cls = classified
|
||||
message = commit["commit"]["message"]
|
||||
trailer = next((line.strip() for line in message.splitlines() if re.match(r"(?i)co-authored-by:|generated with", line.strip())), "")
|
||||
suffix = Path(target["filename"]).suffix
|
||||
language = {".py": "python", ".ts": "typescript", ".tsx": "typescript"}.get(suffix, "javascript")
|
||||
base = re.sub(r"[^a-z0-9]+", "-", f"{row['repo'].split('/')[-1]}-{Path(target['filename']).stem}".lower()).strip("-")[:56]
|
||||
name = f"{base}-{row['sha'][:6]}"
|
||||
per_repo[row["repo"]] = per_repo.get(row["repo"], 0) + 1
|
||||
recipes.append(
|
||||
{
|
||||
"name": name,
|
||||
"host": "github",
|
||||
"repo": row["repo"],
|
||||
"parent": parents[0]["sha"],
|
||||
"commit": commit["sha"],
|
||||
"path": target["filename"],
|
||||
"mode": "hunk",
|
||||
"language": language,
|
||||
"relpath": target["filename"],
|
||||
"license": license_id,
|
||||
"cve": "",
|
||||
"year": int(str(commit["commit"]["author"]["date"])[:4]),
|
||||
"cwe": cwe,
|
||||
"class": cls,
|
||||
"mechanism": mechanism,
|
||||
"provenance": "agent",
|
||||
"origin": "github-agent-trailer",
|
||||
"project": row["repo"].split("/")[-1],
|
||||
"trailer": trailer[:120],
|
||||
"reviewer": "pending",
|
||||
"evidence": title[:200],
|
||||
"commit_url": f"https://github.com/{row['repo']}/commit/{commit['sha']}",
|
||||
}
|
||||
)
|
||||
for index, recipe in enumerate(sorted(recipes, key=lambda r: str(r["name"]))):
|
||||
recipe["split"] = "holdout" if index % 2 else "train"
|
||||
return recipes, skipped
|
||||
|
||||
|
||||
def to_toml(recipes: list[dict[str, object]]) -> str:
|
||||
lines = [
|
||||
"# agent-vfc candidate recipes from agent-trailer security-fix commits (build_recipes.py).",
|
||||
'# reviewer = "pending" means a human has not yet confirmed the vulnerability and mechanism.',
|
||||
"",
|
||||
]
|
||||
for recipe in sorted(recipes, key=lambda r: str(r["name"])):
|
||||
lines.append("[[recipe]]")
|
||||
for key, value in recipe.items():
|
||||
if isinstance(value, int) and not isinstance(value, bool):
|
||||
lines.append(f"{key} = {value}")
|
||||
else:
|
||||
lines.append(f'{key} = "{str(value).replace(chr(92), chr(92) * 2).replace(chr(34), chr(92) + chr(34))}"')
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--search", type=Path, help="run the GitHub commit search and write candidates to this jsonl")
|
||||
parser.add_argument("--from", dest="source", type=Path, help="candidate jsonl to resolve into recipes")
|
||||
parser.add_argument("--limit", type=int, default=40)
|
||||
parser.add_argument("--max-lines", type=int, default=80)
|
||||
parser.add_argument("--out", type=Path, default=ROOT / "recipes.toml")
|
||||
args = parser.parse_args(argv)
|
||||
if args.search:
|
||||
print(f"searched {search(args.search)} candidates -> {args.search}")
|
||||
if args.source:
|
||||
recipes, skipped = build(args.source, limit=args.limit, max_lines=args.max_lines)
|
||||
args.out.write_text(to_toml(recipes), encoding="utf-8")
|
||||
print(f"wrote {args.out} ({len(recipes)} recipes); skipped {skipped}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,91 @@
|
||||
// Provenance: Cap-go/capgo.app (fixed).
|
||||
// repo: Cap-go/capgo.app
|
||||
// commit: 4dadd2580d02213d227a331eee0232aa59859b59
|
||||
// parent: 8c0ac7e233946abd8dc26581b871e9fcd0928899
|
||||
// commit_url: https://github.com/Cap-go/capgo.app/commit/4dadd2580d02213d227a331eee0232aa59859b59
|
||||
// cve:
|
||||
// license: AGPL-3.0
|
||||
// function: next
|
||||
// relpath: supabase/functions/_backend/utils/hono.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export function createHono(functionName: string, _version: string) {
|
||||
let appGlobal
|
||||
if (getRuntimeKey() === 'deno') {
|
||||
appGlobal = new Hono<MiddlewareKeyVariables>().basePath(`/${functionName}`)
|
||||
}
|
||||
else {
|
||||
appGlobal = new Hono<MiddlewareKeyVariables>()
|
||||
}
|
||||
|
||||
// Plugin hot paths (/updates|/stats|/channel_self and the CF plugin worker).
|
||||
// HAR/CPU inspect showed middleware + logging dominating non-DB request cost.
|
||||
const pluginHotPath = functionName === 'plugin'
|
||||
|| functionName === 'updates'
|
||||
|| functionName === 'stats'
|
||||
|| functionName === 'channel_self'
|
||||
|
||||
appGlobal.use('*', (c, next): Promise<any> => {
|
||||
// ADD HEADER TO IDENTIFY WORKER SOURCE
|
||||
const name = `${getEnv(c, 'ENV_NAME') || functionName}-${CapgoVersion}`
|
||||
c.header('X-Worker-Source', name)
|
||||
const hostname = new URL(c.req.url).hostname
|
||||
if (!isPreviewHost(hostname))
|
||||
c.header('Content-Security-Policy', API_CONTENT_SECURITY_POLICY)
|
||||
return next()
|
||||
})
|
||||
|
||||
// Echo ACAO after the handler so Capacitor WebView origins work on routes
|
||||
// that forgot useCors (GET /ok). Do not mount hono cors globally: it
|
||||
// short-circuits OPTIONS and strips TUS discovery headers.
|
||||
if (!pluginHotPath) {
|
||||
appGlobal.use('*', async (c, next) => {
|
||||
await next()
|
||||
const origin = c.req.header('origin')
|
||||
if (!origin)
|
||||
return
|
||||
const allowed = getAllowedCorsOrigin(origin, c)
|
||||
if (allowed) {
|
||||
c.header('Access-Control-Allow-Origin', allowed)
|
||||
c.header('Vary', 'Origin', { append: true })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Skip hono's access logger on plugin hot paths — it serializes every request
|
||||
// on millions of device calls/day.
|
||||
if (!pluginHotPath)
|
||||
appGlobal.use('*', logger())
|
||||
// Use platform-specific request IDs, fallback to generated UUID.
|
||||
// Do not cloudlog inside the generator: it runs on every request (incl. cf-ray).
|
||||
appGlobal.use('*', requestId({
|
||||
generator: (c) => {
|
||||
// Cloudflare provides the Ray ID in the cf-ray header
|
||||
// Check this first as it's our primary deployment target
|
||||
const cfRay = c.req.header('cf-ray')
|
||||
if (cfRay)
|
||||
return cfRay
|
||||
// Supabase Edge Functions provide SB_EXECUTION_ID
|
||||
const sbExecutionId = getEnv(c, 'SB_EXECUTION_ID')
|
||||
if (sbExecutionId)
|
||||
return sbExecutionId
|
||||
// Fallback to crypto.randomUUID() if not on any known platform
|
||||
return crypto.randomUUID()
|
||||
},
|
||||
}))
|
||||
|
||||
appGlobal.post('/ok', (c) => {
|
||||
return c.json(BRES)
|
||||
})
|
||||
appGlobal.post('/ko', (c) => {
|
||||
const defaultResponse: SimpleErrorResponse = {
|
||||
error: 'unknown_error',
|
||||
message: 'KO',
|
||||
moreInfo: {},
|
||||
}
|
||||
return c.json(defaultResponse, 500)
|
||||
})
|
||||
|
||||
return appGlobal
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Provenance: Cap-go/capgo.app (vuln).
|
||||
// repo: Cap-go/capgo.app
|
||||
// commit: 8c0ac7e233946abd8dc26581b871e9fcd0928899
|
||||
// parent: 8c0ac7e233946abd8dc26581b871e9fcd0928899
|
||||
// commit_url: https://github.com/Cap-go/capgo.app/commit/4dadd2580d02213d227a331eee0232aa59859b59
|
||||
// cve:
|
||||
// license: AGPL-3.0
|
||||
// function: next
|
||||
// relpath: supabase/functions/_backend/utils/hono.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export function createHono(functionName: string, _version: string) {
|
||||
let appGlobal
|
||||
if (getRuntimeKey() === 'deno') {
|
||||
appGlobal = new Hono<MiddlewareKeyVariables>().basePath(`/${functionName}`)
|
||||
}
|
||||
else {
|
||||
appGlobal = new Hono<MiddlewareKeyVariables>()
|
||||
}
|
||||
|
||||
// Plugin hot paths (/updates|/stats|/channel_self and the CF plugin worker).
|
||||
// HAR/CPU inspect showed middleware + logging dominating non-DB request cost.
|
||||
const pluginHotPath = functionName === 'plugin'
|
||||
|| functionName === 'updates'
|
||||
|| functionName === 'stats'
|
||||
|| functionName === 'channel_self'
|
||||
|
||||
appGlobal.use('*', (c, next): Promise<any> => {
|
||||
// ADD HEADER TO IDENTIFY WORKER SOURCE
|
||||
const name = `${getEnv(c, 'ENV_NAME') || functionName}-${CapgoVersion}`
|
||||
c.header('X-Worker-Source', name)
|
||||
const hostname = new URL(c.req.url).hostname
|
||||
if (!isPreviewHost(hostname))
|
||||
c.header('Content-Security-Policy', API_CONTENT_SECURITY_POLICY)
|
||||
return next()
|
||||
})
|
||||
|
||||
// Skip hono's access logger on plugin hot paths — it serializes every request
|
||||
// on millions of device calls/day.
|
||||
if (!pluginHotPath)
|
||||
appGlobal.use('*', logger())
|
||||
// Use platform-specific request IDs, fallback to generated UUID.
|
||||
// Do not cloudlog inside the generator: it runs on every request (incl. cf-ray).
|
||||
appGlobal.use('*', requestId({
|
||||
generator: (c) => {
|
||||
// Cloudflare provides the Ray ID in the cf-ray header
|
||||
// Check this first as it's our primary deployment target
|
||||
const cfRay = c.req.header('cf-ray')
|
||||
if (cfRay)
|
||||
return cfRay
|
||||
// Supabase Edge Functions provide SB_EXECUTION_ID
|
||||
const sbExecutionId = getEnv(c, 'SB_EXECUTION_ID')
|
||||
if (sbExecutionId)
|
||||
return sbExecutionId
|
||||
// Fallback to crypto.randomUUID() if not on any known platform
|
||||
return crypto.randomUUID()
|
||||
},
|
||||
}))
|
||||
|
||||
appGlobal.post('/ok', (c) => {
|
||||
return c.json(BRES)
|
||||
})
|
||||
appGlobal.post('/ko', (c) => {
|
||||
const defaultResponse: SimpleErrorResponse = {
|
||||
error: 'unknown_error',
|
||||
message: 'KO',
|
||||
moreInfo: {},
|
||||
}
|
||||
return c.json(defaultResponse, 500)
|
||||
})
|
||||
|
||||
return appGlobal
|
||||
}
|
||||
@@ -0,0 +1,819 @@
|
||||
# CANDIDATES awaiting human review (reviewer = "pending"). Not loaded by load_pair_catalog.
|
||||
# Set `reviewer` in recipes.toml after confirming vulnerability, mechanism, and license; then regenerate.
|
||||
|
||||
# agent-vfc pair slice. Reviewed isolated functions with provenance.
|
||||
# Honesty dashboard — not the local 100% CI gate.
|
||||
# Do not add these names to LANGUAGE_MANIFESTS.
|
||||
# Regenerated by benchmarks/pairs/catalog_gen.py from recipes.toml.
|
||||
|
||||
[[pair]]
|
||||
name = "anastasios-pw-session-14ec1a"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "Anas329796/Anastasios"
|
||||
cve = ""
|
||||
cwe = "CWE-918"
|
||||
commit = "14ec1ac50f9e4e255d875236d30129c6207401d4"
|
||||
parent = "adb7b0d5d6b81c46d56451c709e7eac9d0dc93fb"
|
||||
commit_url = "https://github.com/Anas329796/Anastasios/commit/14ec1ac50f9e4e255d875236d30129c6207401d4"
|
||||
vuln = "anastasios-pw-session-14ec1a/vuln.ts"
|
||||
fixed = "anastasios-pw-session-14ec1a/fixed.ts"
|
||||
relpath = "extensions/browser/src/browser/pw-session.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
path = "extensions/browser/src/browser/pw-session.ts"
|
||||
function = "isTopLevelNavigationRequest"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "fix(browser): harden SSRF redirect guard against non-navigation document hops [AI] (#62355)"
|
||||
|
||||
[[pair]]
|
||||
name = "astroclaw-pw-session-1553a8"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "P1R4N351/astroclaw"
|
||||
cve = ""
|
||||
cwe = "CWE-918"
|
||||
commit = "1553a8adf123913cf7f1f1c75be4c4e5cd6c796b"
|
||||
parent = "d3eed2dc01328f21dd404477bb28e2740fa371a4"
|
||||
commit_url = "https://github.com/P1R4N351/astroclaw/commit/1553a8adf123913cf7f1f1c75be4c4e5cd6c796b"
|
||||
vuln = "astroclaw-pw-session-1553a8/vuln.ts"
|
||||
fixed = "astroclaw-pw-session-1553a8/fixed.ts"
|
||||
relpath = "extensions/browser/src/browser/pw-session.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
path = "extensions/browser/src/browser/pw-session.ts"
|
||||
function = "isTopLevelNavigationRequest"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "fix(browser): harden SSRF redirect guard against non-navigation document hops [AI] (#62355)"
|
||||
|
||||
[[pair]]
|
||||
name = "capgo-app-hono-4dadd2"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "AGPL-3.0"
|
||||
repo = "Cap-go/capgo.app"
|
||||
cve = ""
|
||||
cwe = "CWE-16"
|
||||
commit = "4dadd2580d02213d227a331eee0232aa59859b59"
|
||||
parent = "8c0ac7e233946abd8dc26581b871e9fcd0928899"
|
||||
commit_url = "https://github.com/Cap-go/capgo.app/commit/4dadd2580d02213d227a331eee0232aa59859b59"
|
||||
vuln = "capgo-app-hono-4dadd2/vuln.ts"
|
||||
fixed = "capgo-app-hono-4dadd2/fixed.ts"
|
||||
relpath = "supabase/functions/_backend/utils/hono.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
path = "supabase/functions/_backend/utils/hono.ts"
|
||||
function = "next"
|
||||
mechanism = "permissive_default"
|
||||
evidence = "fix(api): CORS for Capacitor localhost WebView (#3105)"
|
||||
|
||||
[[pair]]
|
||||
name = "dnf-plugin-anyrepo-config-26d19a"
|
||||
slice = "agent-vfc"
|
||||
language = "python"
|
||||
origin = "github-agent-trailer"
|
||||
license = "Apache-2.0"
|
||||
repo = "jfut/dnf-plugin-anyrepo"
|
||||
cve = ""
|
||||
cwe = "CWE-22"
|
||||
commit = "26d19aeb8884f244e34ccfdc4f49f07055adc4d0"
|
||||
parent = "33cde479d0db8f45dd89fbdcfb2bc0f1be66bd7a"
|
||||
commit_url = "https://github.com/jfut/dnf-plugin-anyrepo/commit/26d19aeb8884f244e34ccfdc4f49f07055adc4d0"
|
||||
vuln = "dnf-plugin-anyrepo-config-26d19a/vuln.py"
|
||||
fixed = "dnf-plugin-anyrepo-config-26d19a/fixed.py"
|
||||
relpath = "dnf_plugin_anyrepo/config.py"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "dnf_plugin_anyrepo/config.py"
|
||||
function = "validate_repo_name"
|
||||
mechanism = "path_join_user_input"
|
||||
evidence = "fix(config): prevent path traversal in repository names"
|
||||
|
||||
[[pair]]
|
||||
name = "edutrace-page-ee7ba2"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "Apache-2.0"
|
||||
repo = "jardimdesoftware/edutrace"
|
||||
cve = ""
|
||||
cwe = "CWE-1321"
|
||||
commit = "ee7ba25fb23ea89cc1b67549cb5e32c8ead92739"
|
||||
parent = "c4dc6ddcc5492c77c8a5ad7369c87dea29c001fd"
|
||||
commit_url = "https://github.com/jardimdesoftware/edutrace/commit/ee7ba25fb23ea89cc1b67549cb5e32c8ead92739"
|
||||
vuln = "edutrace-page-ee7ba2/vuln.tsx"
|
||||
fixed = "edutrace-page-ee7ba2/fixed.tsx"
|
||||
relpath = "front/src/app/editar-anamnese/page.tsx"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
path = "front/src/app/editar-anamnese/page.tsx"
|
||||
function = "handleInputChange"
|
||||
mechanism = "prototype_pollution"
|
||||
evidence = "fix(front): impedir prototype pollution nos handlers de formulário aninhado"
|
||||
|
||||
[[pair]]
|
||||
name = "etude-lexical-markdown-editorconfig-c61a8b"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "dayflower/etude-lexical-markdown"
|
||||
cve = ""
|
||||
cwe = "CWE-1321"
|
||||
commit = "c61a8bf78fe20d6ae0eab2e4b8b02004508525ed"
|
||||
parent = "0a2184f59e79a04b1365cd49200026e8f2ffdbd5"
|
||||
commit_url = "https://github.com/dayflower/etude-lexical-markdown/commit/c61a8bf78fe20d6ae0eab2e4b8b02004508525ed"
|
||||
vuln = "etude-lexical-markdown-editorconfig-c61a8b/vuln.ts"
|
||||
fixed = "etude-lexical-markdown-editorconfig-c61a8b/fixed.ts"
|
||||
relpath = "src/config/editorConfig.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
path = "src/config/editorConfig.ts"
|
||||
function = "deepMergeInto"
|
||||
mechanism = "prototype_pollution"
|
||||
evidence = "fix: guard deepMergeInto against prototype pollution"
|
||||
|
||||
[[pair]]
|
||||
name = "etude-lexical-markdown-editorconfig-db4f54"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "dayflower/etude-lexical-markdown"
|
||||
cve = ""
|
||||
cwe = "CWE-1321"
|
||||
commit = "db4f54b1ab80ad596de6425e84f90aa781c49999"
|
||||
parent = "1c865815d05b072f4973388c3ac66b6696d9efde"
|
||||
commit_url = "https://github.com/dayflower/etude-lexical-markdown/commit/db4f54b1ab80ad596de6425e84f90aa781c49999"
|
||||
vuln = "etude-lexical-markdown-editorconfig-db4f54/vuln.ts"
|
||||
fixed = "etude-lexical-markdown-editorconfig-db4f54/fixed.ts"
|
||||
relpath = "src/config/editorConfig.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
path = "src/config/editorConfig.ts"
|
||||
function = "deepMergeInto"
|
||||
mechanism = "prototype_pollution"
|
||||
evidence = "fix: make prototype pollution guard recognizable by CodeQL"
|
||||
|
||||
[[pair]]
|
||||
name = "lensops-kubernetesmanagement-fe4910"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "amitknigam84/lensops"
|
||||
cve = ""
|
||||
cwe = "CWE-862"
|
||||
commit = "fe49109aedfe21dea4d24d4d9f2fa3f1ecfb6c84"
|
||||
parent = "9b87ecc3a44a7fe2a5185cca1fe52441647d5748"
|
||||
commit_url = "https://github.com/amitknigam84/lensops/commit/fe49109aedfe21dea4d24d4d9f2fa3f1ecfb6c84"
|
||||
vuln = "lensops-kubernetesmanagement-fe4910/vuln.tsx"
|
||||
fixed = "lensops-kubernetesmanagement-fe4910/fixed.tsx"
|
||||
relpath = "components/KubernetesManagement.tsx"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-862"
|
||||
class = "missing authorization"
|
||||
path = "components/KubernetesManagement.tsx"
|
||||
function = "setErrorMessage"
|
||||
mechanism = "missing_auth_guard"
|
||||
evidence = "Fix missing auth header on namespaces API call"
|
||||
|
||||
[[pair]]
|
||||
name = "market-cap-route-4f8ae9"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "navaneethbv/market-cap"
|
||||
cve = ""
|
||||
cwe = "CWE-601"
|
||||
commit = "4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6"
|
||||
parent = "fec6f024ce72c9c47b61cbac6ce7a35cb2280602"
|
||||
commit_url = "https://github.com/navaneethbv/market-cap/commit/4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6"
|
||||
vuln = "market-cap-route-4f8ae9/vuln.ts"
|
||||
fixed = "market-cap-route-4f8ae9/fixed.ts"
|
||||
relpath = "app/auth/confirm/route.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-601"
|
||||
class = "open redirect"
|
||||
path = "app/auth/confirm/route.ts"
|
||||
function = "GET"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "Fix open redirects on the auth next param"
|
||||
|
||||
[[pair]]
|
||||
name = "melodix-playerprovider-089931"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "alexshao3/melodix"
|
||||
cve = ""
|
||||
cwe = "CWE-16"
|
||||
commit = "089931ef71ea1e5b7586520baf1a5498e2f05b13"
|
||||
parent = "c074fc7413338aefcbea3170ef4d3ba486a8a4b7"
|
||||
commit_url = "https://github.com/alexshao3/melodix/commit/089931ef71ea1e5b7586520baf1a5498e2f05b13"
|
||||
vuln = "melodix-playerprovider-089931/vuln.tsx"
|
||||
fixed = "melodix-playerprovider-089931/fixed.tsx"
|
||||
relpath = "apps/miniapp/src/components/PlayerProvider.tsx"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
path = "apps/miniapp/src/components/PlayerProvider.tsx"
|
||||
function = "PlayerProvider"
|
||||
mechanism = "permissive_default"
|
||||
evidence = "Merge pull request #17 from alexshao3/devin/1777216143-fix-audio-cors"
|
||||
|
||||
[[pair]]
|
||||
name = "mercado-do-vale-news-catalogmetadataservice-9b5fcf"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "handielson/Mercado-do-vale-news"
|
||||
cve = ""
|
||||
cwe = "CWE-16"
|
||||
commit = "9b5fcf2dae41e56f5f97952266f2d6ba59598598"
|
||||
parent = "70ca282b819ac1d60f4b5e665d224b1043ff1ccc"
|
||||
commit_url = "https://github.com/handielson/Mercado-do-vale-news/commit/9b5fcf2dae41e56f5f97952266f2d6ba59598598"
|
||||
vuln = "mercado-do-vale-news-catalogmetadataservice-9b5fcf/vuln.ts"
|
||||
fixed = "mercado-do-vale-news-catalogmetadataservice-9b5fcf/fixed.ts"
|
||||
relpath = "services/catalogMetadataService.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
path = "services/catalogMetadataService.ts"
|
||||
function = "fetchMetadata"
|
||||
mechanism = "permissive_default"
|
||||
evidence = "fix(catalog): avoid metadata cors preflight"
|
||||
|
||||
[[pair]]
|
||||
name = "money-track-category-icons-4d4a5b"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "andrebubniak/money-track"
|
||||
cve = ""
|
||||
cwe = "CWE-1321"
|
||||
commit = "4d4a5b063278c8b6697c3faae133d7c39fcd01c0"
|
||||
parent = "add96df6d6a6b61506635c23dbacf6c6cfe24dc2"
|
||||
commit_url = "https://github.com/andrebubniak/money-track/commit/4d4a5b063278c8b6697c3faae133d7c39fcd01c0"
|
||||
vuln = "money-track-category-icons-4d4a5b/vuln.ts"
|
||||
fixed = "money-track-category-icons-4d4a5b/fixed.ts"
|
||||
relpath = "src/lib/category-icons.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
path = "src/lib/category-icons.ts"
|
||||
function = "isCategoryIcon"
|
||||
mechanism = "prototype_pollution"
|
||||
evidence = "fix(category-icons): use Object.hasOwn to prevent prototype pollution in type guard"
|
||||
|
||||
[[pair]]
|
||||
name = "nestjs-filter-normalizer-aa0e60"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "DavideCarvalho/nestjs-filter"
|
||||
cve = ""
|
||||
cwe = "CWE-1321"
|
||||
commit = "aa0e600d05997ea3d77538ea1c2db427c439f2e8"
|
||||
parent = "d899b40d3466f2ffbe9f01c4d49267412401f078"
|
||||
commit_url = "https://github.com/DavideCarvalho/nestjs-filter/commit/aa0e600d05997ea3d77538ea1c2db427c439f2e8"
|
||||
vuln = "nestjs-filter-normalizer-aa0e60/vuln.ts"
|
||||
fixed = "nestjs-filter-normalizer-aa0e60/fixed.ts"
|
||||
relpath = "packages/core/src/input/normalizer.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
path = "packages/core/src/input/normalizer.ts"
|
||||
function = "normalizeInput"
|
||||
mechanism = "prototype_pollution"
|
||||
evidence = "fix(core): add prototype pollution guard to normalizeInput"
|
||||
|
||||
[[pair]]
|
||||
name = "new-erp-final-app-6e9644"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "Apache-2.0"
|
||||
repo = "Sachin-Salgar/NEW_ERP_FINAL"
|
||||
cve = ""
|
||||
cwe = "CWE-16"
|
||||
commit = "6e9644c81ce3fb356669157182a5ef09a70c4b59"
|
||||
parent = "08976c5d7a07b0663669b875b4507446199f85d7"
|
||||
commit_url = "https://github.com/Sachin-Salgar/NEW_ERP_FINAL/commit/6e9644c81ce3fb356669157182a5ef09a70c4b59"
|
||||
vuln = "new-erp-final-app-6e9644/vuln.ts"
|
||||
fixed = "new-erp-final-app-6e9644/fixed.ts"
|
||||
relpath = "src/presentation/http/app.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
path = "src/presentation/http/app.ts"
|
||||
function = "origin"
|
||||
mechanism = "permissive_default"
|
||||
evidence = "fix: allow patch requests through cors"
|
||||
|
||||
[[pair]]
|
||||
name = "nimestream-route-d17f53"
|
||||
slice = "agent-vfc"
|
||||
language = "javascript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "Irnhakim/nimestream"
|
||||
cve = ""
|
||||
cwe = "CWE-918"
|
||||
commit = "d17f535bf3012041b056ff3aa991ff6cfa198e43"
|
||||
parent = "0c37bfd9e5292b15b1d7af51f52793d9bdf1cef0"
|
||||
commit_url = "https://github.com/Irnhakim/nimestream/commit/d17f535bf3012041b056ff3aa991ff6cfa198e43"
|
||||
vuln = "nimestream-route-d17f53/vuln.js"
|
||||
fixed = "nimestream-route-d17f53/fixed.js"
|
||||
relpath = "app/api/img/route.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
path = "app/api/img/route.js"
|
||||
function = "GET"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "fix: resolve command injection and SSRF/Open Redirect security issues in multiScraper and image proxy API"
|
||||
|
||||
[[pair]]
|
||||
name = "openniw-jobs-0fc947"
|
||||
slice = "agent-vfc"
|
||||
language = "python"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "HHHHHejia/openniw"
|
||||
cve = ""
|
||||
cwe = "CWE-639"
|
||||
commit = "0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10"
|
||||
parent = "4d91ed82fa9a5ec6bf5ef96da1d221fc187700dc"
|
||||
commit_url = "https://github.com/HHHHHejia/openniw/commit/0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10"
|
||||
vuln = "openniw-jobs-0fc947/vuln.py"
|
||||
fixed = "openniw-jobs-0fc947/fixed.py"
|
||||
relpath = "backend/app/routers/jobs.py"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
path = "backend/app/routers/jobs.py"
|
||||
function = "get_job"
|
||||
mechanism = "identity_from_request_body"
|
||||
evidence = "Fix IDOR on job endpoint: case-bound jobs require case ownership"
|
||||
|
||||
[[pair]]
|
||||
name = "openniw-jobs-b74de3"
|
||||
slice = "agent-vfc"
|
||||
language = "python"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "ziyuzuo/openniw"
|
||||
cve = ""
|
||||
cwe = "CWE-639"
|
||||
commit = "b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68"
|
||||
parent = "98a0c392ba96cd2c4aa746dd6fc2b183f385225e"
|
||||
commit_url = "https://github.com/ziyuzuo/openniw/commit/b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68"
|
||||
vuln = "openniw-jobs-b74de3/vuln.py"
|
||||
fixed = "openniw-jobs-b74de3/fixed.py"
|
||||
relpath = "backend/app/routers/jobs.py"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
path = "backend/app/routers/jobs.py"
|
||||
function = "get_job"
|
||||
mechanism = "identity_from_request_body"
|
||||
evidence = "Fix IDOR on job endpoint: case-bound jobs require case ownership"
|
||||
|
||||
[[pair]]
|
||||
name = "overleaf-with-claude-exportscontroller-3980b9"
|
||||
slice = "agent-vfc"
|
||||
language = "javascript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "AGPL-3.0"
|
||||
repo = "ZUENS2020/overleaf-with-claude"
|
||||
cve = ""
|
||||
cwe = "CWE-639"
|
||||
commit = "3980b9e5806defb63e45ae2696e6c1899f3a8431"
|
||||
parent = "5a886aa9fb9fe4e2203f3cb1d62c91f4be0525ed"
|
||||
commit_url = "https://github.com/ZUENS2020/overleaf-with-claude/commit/3980b9e5806defb63e45ae2696e6c1899f3a8431"
|
||||
vuln = "overleaf-with-claude-exportscontroller-3980b9/vuln.mjs"
|
||||
fixed = "overleaf-with-claude-exportscontroller-3980b9/fixed.mjs"
|
||||
relpath = "services/web/app/src/Features/Exports/ExportsController.mjs"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
path = "services/web/app/src/Features/Exports/ExportsController.mjs"
|
||||
function = "exportProject"
|
||||
mechanism = "identity_from_request_body"
|
||||
evidence = "Fix IDOR in exports by adding token verification (Issue #31637) (#32883)"
|
||||
|
||||
[[pair]]
|
||||
name = "popmark-editorconfig-e5ac40"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "dayflower/popmark"
|
||||
cve = ""
|
||||
cwe = "CWE-1321"
|
||||
commit = "e5ac407cef37c37178d440541ede301c838640fb"
|
||||
parent = "31d1ac79b4cfa3118597348e79800a6561115149"
|
||||
commit_url = "https://github.com/dayflower/popmark/commit/e5ac407cef37c37178d440541ede301c838640fb"
|
||||
vuln = "popmark-editorconfig-e5ac40/vuln.ts"
|
||||
fixed = "popmark-editorconfig-e5ac40/fixed.ts"
|
||||
relpath = "src/lexical-markdown/config/editorConfig.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
path = "src/lexical-markdown/config/editorConfig.ts"
|
||||
function = "deepMergeInto"
|
||||
mechanism = "prototype_pollution"
|
||||
evidence = "fix: guard deepMergeInto against prototype pollution"
|
||||
|
||||
[[pair]]
|
||||
name = "rag-pipeline-utils-config-handler-76e5f0"
|
||||
slice = "agent-vfc"
|
||||
language = "javascript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "DevilsDev/rag-pipeline-utils"
|
||||
cve = ""
|
||||
cwe = "CWE-1321"
|
||||
commit = "76e5f0a94d6803d0e463d26a61cedb7da90857a7"
|
||||
parent = "ba587867118f703632ff2dc63c4feb8ad6793420"
|
||||
commit_url = "https://github.com/DevilsDev/rag-pipeline-utils/commit/76e5f0a94d6803d0e463d26a61cedb7da90857a7"
|
||||
vuln = "rag-pipeline-utils-config-handler-76e5f0/vuln.js"
|
||||
fixed = "rag-pipeline-utils-config-handler-76e5f0/fixed.js"
|
||||
relpath = "src/cli/handlers/config-handler.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
path = "src/cli/handlers/config-handler.js"
|
||||
function = "handleConfigSet"
|
||||
mechanism = "prototype_pollution"
|
||||
evidence = "fix(security): prevent prototype pollution in config-handler"
|
||||
|
||||
[[pair]]
|
||||
name = "registry-proxy-worker-426847"
|
||||
slice = "agent-vfc"
|
||||
language = "javascript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "agents-repo/registry-proxy"
|
||||
cve = ""
|
||||
cwe = "CWE-16"
|
||||
commit = "426847899eb2ee94ae4e5a3aacc50423e36d2dc8"
|
||||
parent = "6d5937972510cdb5ebca30607b538fdc2e280094"
|
||||
commit_url = "https://github.com/agents-repo/registry-proxy/commit/426847899eb2ee94ae4e5a3aacc50423e36d2dc8"
|
||||
vuln = "registry-proxy-worker-426847/vuln.js"
|
||||
fixed = "registry-proxy-worker-426847/fixed.js"
|
||||
relpath = "src/worker.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
path = "src/worker.js"
|
||||
function = "buildUpstreamRequest"
|
||||
mechanism = "permissive_default"
|
||||
evidence = "fix: handle CORS OPTIONS preflight for catalog fetches (#10)"
|
||||
|
||||
[[pair]]
|
||||
name = "supplieradvisor-mvp-route-387bcf"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "bigfivefoods/supplieradvisor-mvp"
|
||||
cve = ""
|
||||
cwe = "CWE-639"
|
||||
commit = "387bcf40e984a2ee1832ab7beabf0284c5b627d8"
|
||||
parent = "a7a9bc260d649ea2e582c07435bfd7d93100647b"
|
||||
commit_url = "https://github.com/bigfivefoods/supplieradvisor-mvp/commit/387bcf40e984a2ee1832ab7beabf0284c5b627d8"
|
||||
vuln = "supplieradvisor-mvp-route-387bcf/vuln.ts"
|
||||
fixed = "supplieradvisor-mvp-route-387bcf/fixed.ts"
|
||||
relpath = "app/api/customers/claims/route.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
path = "app/api/customers/claims/route.ts"
|
||||
function = "PATCH"
|
||||
mechanism = "identity_from_request_body"
|
||||
evidence = "Brief 62: Fix IDOR on customer_claims PATCH/DELETE (#156)"
|
||||
|
||||
[[pair]]
|
||||
name = "supplieradvisor-mvp-route-a69e8f"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "bigfivefoods/supplieradvisor-mvp"
|
||||
cve = ""
|
||||
cwe = "CWE-639"
|
||||
commit = "a69e8f27c0f4d402573d16f0612b51155bbc46e1"
|
||||
parent = "8558538471e4fb10856f8d9a17d2be5ab5c4fb9c"
|
||||
commit_url = "https://github.com/bigfivefoods/supplieradvisor-mvp/commit/a69e8f27c0f4d402573d16f0612b51155bbc46e1"
|
||||
vuln = "supplieradvisor-mvp-route-a69e8f/vuln.ts"
|
||||
fixed = "supplieradvisor-mvp-route-a69e8f/fixed.ts"
|
||||
relpath = "app/api/customers/opportunities/route.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
path = "app/api/customers/opportunities/route.ts"
|
||||
function = "GET"
|
||||
mechanism = "identity_from_request_body"
|
||||
evidence = "Brief 60: Fix IDOR on opportunities GET/PATCH/DELETE (missing company membership checks) (#148)"
|
||||
|
||||
[[pair]]
|
||||
name = "tools-cli-tools-a96bc0"
|
||||
slice = "agent-vfc"
|
||||
language = "python"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "D-sorganization/Tools"
|
||||
cve = ""
|
||||
cwe = "CWE-78"
|
||||
commit = "a96bc0502a3dcdac303e4f0152508886e5c35c0a"
|
||||
parent = "e735d28b82dd1fbc42c0ae01157b38d1b4c7c864"
|
||||
commit_url = "https://github.com/D-sorganization/Tools/commit/a96bc0502a3dcdac303e4f0152508886e5c35c0a"
|
||||
vuln = "tools-cli-tools-a96bc0/vuln.py"
|
||||
fixed = "tools-cli-tools-a96bc0/fixed.py"
|
||||
relpath = "src/shared/python/ai/tools/cli_tools.py"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "src/shared/python/ai/tools/cli_tools.py"
|
||||
function = "_is_command_allowed"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "🛡️ Sentinel: [CRITICAL] Fix command injection in ShellTool (#3307)"
|
||||
|
||||
[[pair]]
|
||||
name = "trackly-cli-path-diagnostics-1c1aed"
|
||||
slice = "agent-vfc"
|
||||
language = "javascript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "trackly-app/trackly-cli"
|
||||
cve = ""
|
||||
cwe = "CWE-22"
|
||||
commit = "1c1aed89b07edb04051830c8f086e02b65e961c6"
|
||||
parent = "8d240ad8d7fc114c8f941ad956a2fdf32391ff60"
|
||||
commit_url = "https://github.com/trackly-app/trackly-cli/commit/1c1aed89b07edb04051830c8f086e02b65e961c6"
|
||||
vuln = "trackly-cli-path-diagnostics-1c1aed/vuln.js"
|
||||
fixed = "trackly-cli-path-diagnostics-1c1aed/fixed.js"
|
||||
relpath = "lib/path-diagnostics.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "lib/path-diagnostics.js"
|
||||
function = "inspectExistingAncestor"
|
||||
mechanism = "path_join_user_input"
|
||||
evidence = "fix(apply): report blocked path traversal"
|
||||
|
||||
[[pair]]
|
||||
name = "upstreamdrift-local-server-c3a078"
|
||||
slice = "agent-vfc"
|
||||
language = "python"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "D-sorganization/UpstreamDrift"
|
||||
cve = ""
|
||||
cwe = "CWE-22"
|
||||
commit = "c3a0787080489b30e2ed0abfac03b51e45da184b"
|
||||
parent = "e28d1da5e103d93951ef11b78a6e9b89ac1fa2bc"
|
||||
commit_url = "https://github.com/D-sorganization/UpstreamDrift/commit/c3a0787080489b30e2ed0abfac03b51e45da184b"
|
||||
vuln = "upstreamdrift-local-server-c3a078/vuln.py"
|
||||
fixed = "upstreamdrift-local-server-c3a078/fixed.py"
|
||||
relpath = "src/api/local_server.py"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "src/api/local_server.py"
|
||||
function = "_find_logo_file"
|
||||
mechanism = "path_join_user_input"
|
||||
evidence = "fix(api): harden local server path traversal (#2805) (#2839)"
|
||||
|
||||
[[pair]]
|
||||
name = "waggledance-swarm-ssrf-host-guard-9a4548"
|
||||
slice = "agent-vfc"
|
||||
language = "python"
|
||||
origin = "github-agent-trailer"
|
||||
license = "Apache-2.0"
|
||||
repo = "Ahkeratmehilaiset/waggledance-swarm"
|
||||
cve = ""
|
||||
cwe = "CWE-918"
|
||||
commit = "9a454843aa35332ff2eb3106023eee0c4b5e444b"
|
||||
parent = "934b939f1cca5259eaf807db3319eb97b90d8d80"
|
||||
commit_url = "https://github.com/Ahkeratmehilaiset/waggledance-swarm/commit/9a454843aa35332ff2eb3106023eee0c4b5e444b"
|
||||
vuln = "waggledance-swarm-ssrf-host-guard-9a4548/vuln.py"
|
||||
fixed = "waggledance-swarm-ssrf-host-guard-9a4548/fixed.py"
|
||||
relpath = "waggledance/core/v3_13_0/ssrf_host_guard.py"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
path = "waggledance/core/v3_13_0/ssrf_host_guard.py"
|
||||
function = "normalize_allowed_hosts"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "fix(ssrf): reject bare-string allowed hosts (#1460)"
|
||||
|
||||
[[pair]]
|
||||
name = "workers-research-utils-209444"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "G4brym/workers-research"
|
||||
cve = ""
|
||||
cwe = "CWE-89"
|
||||
commit = "209444eb61cc564c2d6b43267256f85fe3e5e30e"
|
||||
parent = "eab923ad3099c01b002fbd6be7cf994614bbdee4"
|
||||
commit_url = "https://github.com/G4brym/workers-research/commit/209444eb61cc564c2d6b43267256f85fe3e5e30e"
|
||||
vuln = "workers-research-utils-209444/vuln.ts"
|
||||
fixed = "workers-research-utils-209444/fixed.ts"
|
||||
relpath = "src/utils.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-89"
|
||||
class = "sql injection"
|
||||
path = "src/utils.ts"
|
||||
function = "formatDuration"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "Fix SQL injection in search by using parameterized queries (#41)"
|
||||
|
||||
[[pair]]
|
||||
name = "zoonk-origin-bfbf67"
|
||||
slice = "agent-vfc"
|
||||
language = "typescript"
|
||||
origin = "github-agent-trailer"
|
||||
license = "MIT"
|
||||
repo = "zoonk/zoonk"
|
||||
cve = ""
|
||||
cwe = "CWE-16"
|
||||
commit = "bfbf670ccb41d63c407d32c51bd26e626a174f31"
|
||||
parent = "2604269350bff51f58572c133b45010cb0976a5a"
|
||||
commit_url = "https://github.com/zoonk/zoonk/commit/bfbf670ccb41d63c407d32c51bd26e626a174f31"
|
||||
vuln = "zoonk-origin-bfbf67/vuln.ts"
|
||||
fixed = "zoonk-origin-bfbf67/fixed.ts"
|
||||
relpath = "packages/utils/src/origin.ts"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "agent"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
path = "packages/utils/src/origin.ts"
|
||||
function = "getAllowedHosts"
|
||||
mechanism = "permissive_default"
|
||||
evidence = "fix(api): allow staging cors from previews (#1559)"
|
||||
@@ -0,0 +1,4 @@
|
||||
# agent-vfc pair slice. Reviewed isolated functions with provenance.
|
||||
# Honesty dashboard — not the local 100% CI gate.
|
||||
# Do not add these names to LANGUAGE_MANIFESTS.
|
||||
# Regenerated by benchmarks/pairs/catalog_gen.py from recipes.toml.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Provenance: jfut/dnf-plugin-anyrepo (fixed).
|
||||
# repo: jfut/dnf-plugin-anyrepo
|
||||
# commit: 26d19aeb8884f244e34ccfdc4f49f07055adc4d0
|
||||
# parent: 33cde479d0db8f45dd89fbdcfb2bc0f1be66bd7a
|
||||
# commit_url: https://github.com/jfut/dnf-plugin-anyrepo/commit/26d19aeb8884f244e34ccfdc4f49f07055adc4d0
|
||||
# cve:
|
||||
# license: Apache-2.0
|
||||
# function: validate_repo_name
|
||||
# relpath: dnf_plugin_anyrepo/config.py
|
||||
# provenance: agent
|
||||
# mechanism: path_join_user_input
|
||||
|
||||
def validate_repo_name(name: str) -> str:
|
||||
"""Validate the INI section name used as the repository alias."""
|
||||
|
||||
normalized = str(name).strip()
|
||||
if not normalized:
|
||||
raise ConfigError("repository name must not be empty")
|
||||
if normalized == "main":
|
||||
raise ConfigError("repository name must not be main")
|
||||
# Keep the alias from resolving to the cache directory itself or its parent.
|
||||
if normalized in {".", ".."}:
|
||||
raise ConfigError(f"invalid repository name: {name}")
|
||||
if any(char in normalized for char in "\x00\r\n[]/\\"):
|
||||
raise ConfigError(f"invalid repository name: {name}")
|
||||
return normalized
|
||||
@@ -0,0 +1,23 @@
|
||||
# Provenance: jfut/dnf-plugin-anyrepo (vuln).
|
||||
# repo: jfut/dnf-plugin-anyrepo
|
||||
# commit: 33cde479d0db8f45dd89fbdcfb2bc0f1be66bd7a
|
||||
# parent: 33cde479d0db8f45dd89fbdcfb2bc0f1be66bd7a
|
||||
# commit_url: https://github.com/jfut/dnf-plugin-anyrepo/commit/26d19aeb8884f244e34ccfdc4f49f07055adc4d0
|
||||
# cve:
|
||||
# license: Apache-2.0
|
||||
# function: validate_repo_name
|
||||
# relpath: dnf_plugin_anyrepo/config.py
|
||||
# provenance: agent
|
||||
# mechanism: path_join_user_input
|
||||
|
||||
def validate_repo_name(name: str) -> str:
|
||||
"""Validate the INI section name used as the repository alias."""
|
||||
|
||||
normalized = str(name).strip()
|
||||
if not normalized:
|
||||
raise ConfigError("repository name must not be empty")
|
||||
if normalized == "main":
|
||||
raise ConfigError("repository name must not be main")
|
||||
if any(char in normalized for char in "\r\n[]"):
|
||||
raise ConfigError(f"invalid repository name: {name}")
|
||||
return normalized
|
||||
@@ -0,0 +1,442 @@
|
||||
// Provenance: jardimdesoftware/edutrace (fixed).
|
||||
// repo: jardimdesoftware/edutrace
|
||||
// commit: ee7ba25fb23ea89cc1b67549cb5e32c8ead92739
|
||||
// parent: c4dc6ddcc5492c77c8a5ad7369c87dea29c001fd
|
||||
// commit_url: https://github.com/jardimdesoftware/edutrace/commit/ee7ba25fb23ea89cc1b67549cb5e32c8ead92739
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: handleInputChange
|
||||
// relpath: front/src/app/editar-anamnese/page.tsx
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function AnamnesePage() {
|
||||
const searchParams = useSearchParams();
|
||||
const email = searchParams.get("email");
|
||||
const nome = searchParams.get("nome");
|
||||
|
||||
const { loading } = useAuth();
|
||||
const router = useRouter();
|
||||
|
||||
const [anamnesis, setAnamnesis] = useState<AnamnesisData | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const [formData, setFormData] = useState<AnamnesisData>(initialAnamnesisState);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const token = decodeToken();
|
||||
if (!token) {
|
||||
router.push('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
const isStudent = token.id_level === ESTUDANTE;
|
||||
|
||||
if (token.id_level === PROFISSIONAL_EDUCACAO || isStudent) {
|
||||
router.push(`/anamnese${email ? `?email=${email}&nome=${nome}` : ''}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const target = isStudent ? token.email : email;
|
||||
|
||||
if (target) {
|
||||
const data = await getAnamneseByEmail(target);
|
||||
setAnamnesis(data);
|
||||
setFormData(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Anamnese não encontrada, iniciando modo de criação.", error);
|
||||
setAnamnesis(null);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
fetchData();
|
||||
}, [email, nome, router]);
|
||||
|
||||
|
||||
const handleInputChange = (name: string, value: string) => {
|
||||
const keys = name.split('.');
|
||||
if (keys.some((key) => key === '__proto__' || key === 'constructor' || key === 'prototype')) return;
|
||||
|
||||
setFormData(prevData => {
|
||||
const newData = JSON.parse(JSON.stringify(prevData));
|
||||
let current = newData;
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
current = current[keys[i]];
|
||||
}
|
||||
current[keys[keys.length - 1]] = value;
|
||||
return newData;
|
||||
});
|
||||
};
|
||||
|
||||
const handleCheckboxClick = (name: string) => {
|
||||
const keys = name.split('.');
|
||||
if (keys.some((key) => key === '__proto__' || key === 'constructor' || key === 'prototype')) return;
|
||||
|
||||
setFormData(prevData => {
|
||||
// Criar uma cópia profunda para segurança
|
||||
const newData = JSON.parse(JSON.stringify(prevData));
|
||||
|
||||
let currentSection = newData;
|
||||
// Navega até o penúltimo nível do objeto
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
currentSection = currentSection[keys[i]];
|
||||
}
|
||||
|
||||
const finalKey = keys[keys.length - 1];
|
||||
const currentValue = currentSection[finalKey];
|
||||
|
||||
// Inverte o valor booleano atual
|
||||
currentSection[finalKey] = !currentValue;
|
||||
|
||||
return newData;
|
||||
});
|
||||
};
|
||||
|
||||
const handleEdit = async () => {
|
||||
if (!email) {
|
||||
alert("Email do estudante não encontrado para editar anamnese.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dadosAtualizados = { ...formData };
|
||||
await patchAnamnesis(dadosAtualizados, email);
|
||||
alert("Anamnese atualizada com sucesso!");
|
||||
router.push(`/estudantes/visualizar?email=${email}&nome=${nome}`);
|
||||
} catch (error) {
|
||||
console.error("Erro ao atualizar Anamnese: ", error);
|
||||
alert("Falha ao atualizar Anamnese. Verifique o console para mais detalhes.");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (isLoading || loading) {
|
||||
return <h1>Carregando...</h1>; //ADICIONAR COMPONENTE DE LOADING
|
||||
}
|
||||
|
||||
if (anamnesis === null) {
|
||||
return (
|
||||
<AppLayout
|
||||
>
|
||||
<div className="p-6 text-center">
|
||||
<h2 className="text-xl font-bold text-green-700">O estudante ainda não possui uma Anamnese cadastrada</h2>
|
||||
<button className="mt-6 bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-full" onClick={() => router.push(`/estudantes/visualizar?email=${email}&nome=${nome}`)}>
|
||||
Voltar
|
||||
</button>
|
||||
</div>
|
||||
</AppLayout>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<AppLayout
|
||||
>
|
||||
<div className="p-6 space-y-8 w-full">
|
||||
<h1 className="text-3xl font-bold text-gray-800">Editar Anamnese</h1>
|
||||
|
||||
{/* Identificação */}
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold mb-4">Identificação</h2>
|
||||
<div className="grid md:grid-cols-4 gap-4">
|
||||
<BrInput label="Nome da unidade plena" value={formData.identification.nome_unidade_plena} onInput={(e: any) => handleInputChange('identification.nome_unidade_plena', e.target.value)} />
|
||||
<BrInput label="Nome completo" value={formData.identification.nome_completo} onInput={(e: any) => handleInputChange('identification.nome_completo', e.target.value)} />
|
||||
<BrInput label="Data de Nascimento" value={formData.identification.data_de_nascimento} onInput={(e: any) => handleInputChange('identification.data_de_nascimento', e.target.value)} />
|
||||
<BrInput label="Endereço" value={formData.identification.endereco} onInput={(e: any) => handleInputChange('identification.endereco', e.target.value)} />
|
||||
<BrInput label="Bairro" value={formData.identification.bairo} onInput={(e: any) => handleInputChange('identification.bairo', e.target.value)} />
|
||||
<BrInput label="CEP" value={formData.identification.cep} onInput={(e: any) => handleInputChange('identification.cep', e.target.value)} />
|
||||
<BrInput label="Município" value={formData.identification.municipio} onInput={(e: any) => handleInputChange('identification.municipio', e.target.value)} />
|
||||
<BrInput label="Curso" value={formData.identification.curso} onInput={(e: any) => handleInputChange('identification.curso', e.target.value)} />
|
||||
<BrInput label="Série de escolaridade atual" value={formData.identification.serie_de_escolaridade_atual} onInput={(e: any) => handleInputChange('identification.serie_de_escolaridade_atual', e.target.value)} />
|
||||
<BrInput label="Turma" value={formData.identification.turma} onInput={(e: any) => handleInputChange('identification.turma', e.target.value)} />
|
||||
<BrInput label="Idade que iniciou os estudos" value={formData.identification.idade_iniciou_estudos} onInput={(e: any) => handleInputChange('identification.idade_iniciou_estudos', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Dados Familiares */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Dados familiares</h2>
|
||||
<div className="grid md:grid-cols-4 gap-4">
|
||||
<BrInput label="Nome do pai" value={formData.family_data.nome_pai} onInput={(e: any) => handleInputChange('family_data.nome_pai', e.target.value)} />
|
||||
<BrInput label="Profissão do pai" value={formData.family_data.profissao_pai} onInput={(e: any) => handleInputChange('family_data.profissao_pai', e.target.value)} />
|
||||
<BrInput label="Escolaridade do pai" value={formData.family_data.escolaridade_pai} onInput={(e: any) => handleInputChange('family_data.escolaridade_pai', e.target.value)} />
|
||||
<BrInput label="Idade do pai" value={formData.family_data.idade_pai} onInput={(e: any) => handleInputChange('family_data.idade_pai', e.target.value)} />
|
||||
<BrInput label="Nome da mãe" value={formData.family_data.nome_mae} onInput={(e: any) => handleInputChange('family_data.nome_mae', e.target.value)} />
|
||||
<BrInput label="Profissão da mãe" value={formData.family_data.profissao_mae} onInput={(e: any) => handleInputChange('family_data.profissao_mae', e.target.value)} />
|
||||
<BrInput label="Escolaridade da mãe" value={formData.family_data.escolaridade_mae} onInput={(e: any) => handleInputChange('family_data.escolaridade_mae', e.target.value)} />
|
||||
<BrInput label="Idade da mãe" value={formData.family_data.idade_mae} onInput={(e: any) => handleInputChange('family_data.idade_mae', e.target.value)} />
|
||||
<BrInput label="Outros filhos" value={formData.family_data.outros_filhos} onInput={(e: any) => handleInputChange('family_data.outros_filhos', e.target.value)} />
|
||||
</div>
|
||||
<div className="mt-4 space-y-2">
|
||||
<label className="text-sm font-medium text-black">União dos Pais</label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Casados" checked={formData.family_data.uniao_pais.casados} onClick={() => handleCheckboxClick('family_data.uniao_pais.casados')} />
|
||||
<BrCheckbox name="" label="Separados" checked={formData.family_data.uniao_pais.separados} onClick={() => handleCheckboxClick('family_data.uniao_pais.separados')} />
|
||||
<BrCheckbox name="" label="Separados como uma nova estrutura familiar" checked={formData.family_data.uniao_pais.separados_como_nova_estrutura_familia} onClick={() => handleCheckboxClick('family_data.uniao_pais.separados_como_nova_estrutura_familia')} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 space-y-2">
|
||||
<label className="text-sm font-medium text-black">Pais</label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Biológico" checked={formData.family_data.pais.biologico} onClick={() => handleCheckboxClick('family_data.pais.biologico')} />
|
||||
<BrCheckbox name="" label="Adotivo" checked={formData.family_data.pais.adotivo} onClick={() => handleCheckboxClick('family_data.pais.adotivo')} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Em caso de separação, o estudante vive com quem?" value={formData.family_data.estudante_reside_com_quem} onInput={(e: any) => handleInputChange('family_data.estudante_reside_com_quem', e.target.value)} />
|
||||
<BrInput label="Reação do estudante à situação" value={formData.family_data.reacao_estudante_situacao} onInput={(e: any) => handleInputChange('family_data.reacao_estudante_situacao', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Condições familiares do estudante */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Condições familiares do estudante</h2>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Condições de moradia</p>
|
||||
<div className="flex space-x-3">
|
||||
<BrCheckbox name="" label="Taipa" checked={formData.family_conditions.moradia.taipa} onClick={() => handleCheckboxClick('family_conditions.moradia.taipa')} />
|
||||
<BrCheckbox name="" label="Alvenaria" checked={formData.family_conditions.moradia.alvenaria} onClick={() => handleCheckboxClick('family_conditions.moradia.alvenaria')} />
|
||||
<BrCheckbox name="" label="Palafita" checked={formData.family_conditions.moradia.palafita} onClick={() => handleCheckboxClick('family_conditions.moradia.palafita')} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Convívio familiar</p>
|
||||
<div className="flex space-x-3">
|
||||
<BrCheckbox name="" label="Excelente" checked={formData.family_conditions.convivio_familiar.excelente} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.excelente')} />
|
||||
<BrCheckbox name="" label="Bom" checked={formData.family_conditions.convivio_familiar.bom} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.bom')} />
|
||||
<BrCheckbox name="" label="Problemático" checked={formData.family_conditions.convivio_familiar.problematico} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.problematico')} />
|
||||
<BrCheckbox name="" label="Precário" checked={formData.family_conditions.convivio_familiar.precario} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.precario')} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Qualidade de comunicação</p>
|
||||
<div className="flex space-x-3">
|
||||
<BrCheckbox name="" label="Excelente" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.execelente} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.execelente')} />
|
||||
<BrCheckbox name="" label="Boa" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.boa} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.boa')} />
|
||||
<BrCheckbox name="" label="Ruim" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.ruim} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.ruim')} />
|
||||
<BrCheckbox name="" label="Péssima" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.pessima} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.pessima')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-4 mt-6">
|
||||
<BrInput label="Que medidas disciplinares normalmente são usadas com o estudante" value={formData.family_conditions.medidas_disciplinares_com_estudante} onInput={(e: any) => handleInputChange('family_conditions.medidas_disciplinares_com_estudante', e.target.value)} />
|
||||
<BrInput label="Quem as usa" value={formData.family_conditions.quem_usa_medidas_disciplinares} onInput={(e: any) => handleInputChange('family_conditions.quem_usa_medidas_disciplinares', e.target.value)} />
|
||||
<BrInput label="Quais as reações do estudante frente a essas medidas" value={formData.family_conditions.reacao_estudante_frente_medidas} onInput={(e: any) => handleInputChange('family_conditions.reacao_estudante_frente_medidas', e.target.value)} />
|
||||
<BrInput label="Como reage quando contrariado" value={formData.family_conditions.reacao_contrariado} onInput={(e: any) => handleInputChange('family_conditions.reacao_contrariado', e.target.value)} />
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<p className="text-sm font-medium mb-2">Condições do ambiente familiar para a aprendizagem escolar</p>
|
||||
<BrInput label="Condição" value={formData.family_conditions.condicao_ambiente_familiar_aprendizagem_escolar} onInput={(e: any) => handleInputChange('family_conditions.condicao_ambiente_familiar_aprendizagem_escolar', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Histórico da Mãe */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Histórico da Mãe</h2>
|
||||
|
||||
{/* Gestação */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Gestação</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<BrInput label="Transfusão sanguínea na gravidez" value={formData.mother_background.gestacao.transfusao_sanguinea_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.transfusao_sanguinea_gravidez', e.target.value)} />
|
||||
<BrInput label="Quando sentiu movimento da criança" value={formData.mother_background.gestacao.quando_sentiu_movimento_da_crianca} onInput={(e: any) => handleInputChange('mother_background.gestacao.quando_sentiu_movimento_da_crianca', e.target.value)} />
|
||||
<BrInput label="Levou tombo durante a gravidez" value={formData.mother_background.gestacao.levou_tombo_durante_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.levou_tombo_durante_gravidez', e.target.value)} />
|
||||
<BrInput label="Doença na gestação" value={formData.mother_background.gestacao.doenca_na_gestacao} onInput={(e: any) => handleInputChange('mother_background.gestacao.doenca_na_gestacao', e.target.value)} />
|
||||
<BrInput label="Condição de saúde da mãe na gravidez" value={formData.mother_background.gestacao.condicao_saude_da_mae_na_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.condicao_saude_da_mae_na_gravidez', e.target.value)} />
|
||||
<BrInput label="Episódio marcante na gravidez" value={formData.mother_background.gestacao.episodio_marcante_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.episodio_marcante_gravidez', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Condições de Nascimento */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Condições de Nascimento</h3>
|
||||
<div className="grid md:grid-cols-4 gap-4">
|
||||
<BrInput label="Nasceu com quantos meses" value={formData.mother_background.condicoes_nascimento.nasceu_quantos_meses} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.nasceu_quantos_meses', e.target.value)} />
|
||||
<BrInput label="Nasceu com quantos quilos" value={formData.mother_background.condicoes_nascimento.nasceu_quantos_quilos} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.nasceu_quantos_quilos', e.target.value)} />
|
||||
<BrInput label="Nasceu com qual comprimento" value={formData.mother_background.condicoes_nascimento.nasceu_com_qual_comprimento} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.nasceu_com_qual_comprimento', e.target.value)} />
|
||||
<BrInput label="Desenvolvimento do parto" value={formData.mother_background.condicoes_nascimento.desenvolvimento_parto} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.desenvolvimento_parto', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Primeiras Reações */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Primeiras Reações</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<BrInput label="Chorou" value={formData.mother_background.primeiras_reacoes.chorou} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.chorou', e.target.value)} />
|
||||
<BrInput label="Ficou vermelho demais" value={formData.mother_background.primeiras_reacoes.ficou_vermelho_demais} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.ficou_vermelho_demais', e.target.value)} />
|
||||
<BrInput label="Ficou vermelho por quanto tempo" value={formData.mother_background.primeiras_reacoes.ficou_vermelho_por_quanto_tempo} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.ficou_vermelho_por_quanto_tempo', e.target.value)} />
|
||||
<BrInput label="Precisou de oxigênio" value={formData.mother_background.primeiras_reacoes.precisou_de_oxigenio} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.precisou_de_oxigenio', e.target.value)} />
|
||||
<BrInput label="Ficou ictérico" value={formData.mother_background.primeiras_reacoes.ficou_icterico} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.ficou_icterico', e.target.value)} />
|
||||
<BrInput label="Como era quando bebê" value={formData.mother_background.primeiras_reacoes.como_era_quando_bebe} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.como_era_quando_bebe', e.target.value)} />
|
||||
<BrInput label="Qual idade afirmou a cabeça" value={formData.mother_background.primeiras_reacoes.qual_idade_afirmou_cabeca} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_afirmou_cabeca', e.target.value)} />
|
||||
<BrInput label="Qual idade sentou sem apoio" value={formData.mother_background.primeiras_reacoes.qual_idade_sentou_sem_apoio} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_sentou_sem_apoio', e.target.value)} />
|
||||
<BrInput label="Qual idade engatinhou" value={formData.mother_background.primeiras_reacoes.qual_idade_engatinhou} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_engatinhou', e.target.value)} />
|
||||
<BrInput label="Qual idade ficou de pé" value={formData.mother_background.primeiras_reacoes.qual_idade_ficou_de_pe} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_ficou_de_pe', e.target.value)} />
|
||||
<BrInput label="Qual idade andou" value={formData.mother_background.primeiras_reacoes.qual_idade_andou} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_andou', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Linguagem Verbal (3 anos) */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Linguagem Verbal (3 anos)</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Balbuciou" checked={formData.verbal_language_three_years.balbuciou} onClick={() => handleCheckboxClick('verbal_language_three_years.balbuciou')} />
|
||||
<BrCheckbox name="" label="Trocou letras" checked={formData.verbal_language_three_years.trocou_letras} onClick={() => handleCheckboxClick('verbal_language_three_years.trocou_letras')} />
|
||||
<BrCheckbox name="" label="Gaguejou" checked={formData.verbal_language_three_years.gaguejou} onClick={() => handleCheckboxClick('verbal_language_three_years.gaguejou')} />
|
||||
</div>
|
||||
<BrInput label="Primeiras expressões" value={formData.verbal_language_three_years.primeiras_expressoes} onInput={(e: any) => handleInputChange('verbal_language_three_years.primeiras_expressoes', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Desenvolvimento */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Desenvolvimento</h2>
|
||||
|
||||
{/* Saúde */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Saúde</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Sofreu acidente ou fez cirurgia" value={formData.development.saude.sofreu_acidente_ou_fez_cirurgia} onInput={(e: any) => handleInputChange('development.saude.sofreu_acidente_ou_fez_cirurgia', e.target.value)} />
|
||||
<BrInput label="Possui alergia" value={formData.development.saude.possui_alergia} onInput={(e: any) => handleInputChange('development.saude.possui_alergia', e.target.value)} />
|
||||
<BrInput label="Possui bronquite ou asma" value={formData.development.saude.possui_bronquite_ou_asma} onInput={(e: any) => handleInputChange('development.saude.possui_bronquite_ou_asma', e.target.value)} />
|
||||
<BrInput label="Possui problema de visão ou audição" value={formData.development.saude.possui_problema_visao_audicao} onInput={(e: any) => handleInputChange('development.saude.possui_problema_visao_audicao', e.target.value)} />
|
||||
<BrInput label="Já desmaiou" value={formData.development.saude.ja_desmaiou} onInput={(e: any) => handleInputChange('development.saude.ja_desmaiou', e.target.value)} />
|
||||
<BrInput label="Quando desmaiou" value={formData.development.saude.quando_desmaiou} onInput={(e: any) => handleInputChange('development.saude.quando_desmaiou', e.target.value)} />
|
||||
<BrInput label="Teve ou tem convulsões" value={formData.development.saude.teve_ou_tem_convulsoes} onInput={(e: any) => handleInputChange('development.saude.teve_ou_tem_convulsoes', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Alimentação */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Alimentação</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Foi amamentada" value={formData.development.alimentacao.foi_amamentada} onInput={(e: any) => handleInputChange('development.alimentacao.foi_amamentada', e.target.value)} />
|
||||
<BrInput label="Foi amamentada até quando" value={formData.development.alimentacao.foi_amementada_ate_quando} onInput={(e: any) => handleInputChange('development.alimentacao.foi_amementada_ate_quando', e.target.value)} />
|
||||
<BrInput label="Como é sua alimentação" value={formData.development.alimentacao.como_e_sua_alimentacao} onInput={(e: any) => handleInputChange('development.alimentacao.como_e_sua_alimentacao', e.target.value)} />
|
||||
<BrInput label="Foi forçado a se alimentar" value={formData.development.alimentacao.foi_forcado_se_alimentar} onInput={(e: any) => handleInputChange('development.alimentacao.foi_forcado_se_alimentar', e.target.value)} />
|
||||
<BrInput label="Recebe ajuda na alimentação" value={formData.development.alimentacao.recebe_ajuda_na_alimentacao} onInput={(e: any) => handleInputChange('development.alimentacao.recebe_ajuda_na_alimentacao', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sono */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Sono</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Dorme bem" checked={formData.development.sono.dorme_bem} onClick={() => handleCheckboxClick('development.sono.dorme_bem')} />
|
||||
<BrCheckbox name="" label="Dorme separado dos pais" checked={formData.development.sono.dorme_separado_dos_pais} onClick={() => handleCheckboxClick('development.sono.dorme_separado_dos_pais')} />
|
||||
</div>
|
||||
<BrInput label="Com quem dorme" value={formData.development.sono.com_quem_dorme} onInput={(e: any) => handleInputChange('development.sono.com_quem_dorme', e.target.value)} />
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<p className="text-sm font-medium mb-2">Tipo de sono</p>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Agitado" checked={formData.development.sono.sono.agitado} onClick={() => handleCheckboxClick('development.sono.sono.agitado')} />
|
||||
<BrCheckbox name="" label="Tranquilo" checked={formData.development.sono.sono.tranquilo} onClick={() => handleCheckboxClick('development.sono.sono.tranquilo')} />
|
||||
<BrCheckbox name="" label="Fala dormindo" checked={formData.development.sono.sono.fala_dormindo} onClick={() => handleCheckboxClick('development.sono.sono.fala_dormindo')} />
|
||||
<BrCheckbox name="" label="Sonâmbulo" checked={formData.development.sono.sono.sonambulo} onClick={() => handleCheckboxClick('development.sono.sono.sonambulo')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Informações Escolares */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Informações Escolares</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Histórico escolar comum - antecedentes relevantes" value={formData.school_information.historico_escolar_comum_antecedentes_relevantes} onInput={(e: any) => handleInputChange('school_information.historico_escolar_comum_antecedentes_relevantes', e.target.value)} />
|
||||
<BrInput label="Histórico escolar especial - antecedentes relevantes" value={formData.school_information.historico_escolar_especial_antecedentes_relevantes} onInput={(e: any) => handleInputChange('school_information.historico_escolar_especial_antecedentes_relevantes', e.target.value)} />
|
||||
<BrInput label="Deficiência apresentada pelo estudante" value={formData.school_information.deficiencia_apresentada_estudante} onInput={(e: any) => handleInputChange('school_information.deficiencia_apresentada_estudante', e.target.value)} />
|
||||
<BrInput label="Foi retido alguma vez" value={formData.school_information.retido_alguma_vez} onInput={(e: any) => handleInputChange('school_information.retido_alguma_vez', e.target.value)} />
|
||||
<BrInput label="Gosta de ir à escola" value={formData.school_information.gosta_de_ir_escola} onInput={(e: any) => handleInputChange('school_information.gosta_de_ir_escola', e.target.value)} />
|
||||
<BrInput label="É bem aceito pelos amigos" value={formData.school_information.bem_aceito_pelos_amigous} onInput={(e: any) => handleInputChange('school_information.bem_aceito_pelos_amigous', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Sexualidade */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Sexualidade</h2>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Explanação sexual" checked={formData.sexuality.explanacao_sexual} onClick={() => handleCheckboxClick('sexuality.explanacao_sexual')} />
|
||||
<BrCheckbox name="" label="Curiosidade sexual" checked={formData.sexuality.curiosidade_sexual} onClick={() => handleCheckboxClick('sexuality.curiosidade_sexual')} />
|
||||
<BrCheckbox name="" label="Conversa com pais sobre sexualidade" checked={formData.sexuality.conversa_com_pais_sobre_sexualidade} onClick={() => handleCheckboxClick('sexuality.conversa_com_pais_sobre_sexualidade')} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Avaliação do Estudante */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Avaliação do Estudante</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Estudante apresenta outro tipo de deficiência" value={formData.student_assessment.estudante_apresenta_outro_tipo_deficiencia} onInput={(e: any) => handleInputChange('student_assessment.estudante_apresenta_outro_tipo_deficiencia', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Apresenta DA/DF/DI/PC/TGD" checked={formData.student_assessment.apresenta_da_df_di_pc_tgd} onClick={() => handleCheckboxClick('student_assessment.apresenta_da_df_di_pc_tgd')} />
|
||||
</div>
|
||||
<BrInput label="Se sim, data e resultado do diagnóstico" value={formData.student_assessment.se_sim_data_e_resultado_diagnostico} onInput={(e: any) => handleInputChange('student_assessment.se_sim_data_e_resultado_diagnostico', e.target.value)} />
|
||||
<BrInput label="Se não, situação quanto ao diagnóstico - tem outras dificuldades" value={formData.student_assessment.se_não_situacao_quanto_diagnostico_tem_outras_dificuldades} onInput={(e: any) => handleInputChange('student_assessment.se_não_situacao_quanto_diagnostico_tem_outras_dificuldades', e.target.value)} />
|
||||
<BrInput label="Se tem outras dificuldades" value={formData.student_assessment.se_tem_outras_dificuldades} onInput={(e: any) => handleInputChange('student_assessment.se_tem_outras_dificuldades', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Usa medicamentos controlados" checked={formData.student_assessment.usa_medicamentos_controlados} onClick={() => handleCheckboxClick('student_assessment.usa_medicamentos_controlados')} />
|
||||
</div>
|
||||
<BrInput label="Usa quais medicamentos" value={formData.student_assessment.usa_quais_medicamentos} onInput={(e: any) => handleInputChange('student_assessment.usa_quais_medicamentos', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Medicamento interfere na aprendizagem" checked={formData.student_assessment.medicamento_interfere_aprendizagem} onClick={() => handleCheckboxClick('student_assessment.medicamento_interfere_aprendizagem')} />
|
||||
</div>
|
||||
<BrInput label="Se interfere na aprendizagem" value={formData.student_assessment.se_intefere_aprendizagem} onInput={(e: any) => handleInputChange('student_assessment.se_intefere_aprendizagem', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Existem recomendações da saúde" checked={formData.student_assessment.existem_recomendacoes_da_saude} onClick={() => handleCheckboxClick('student_assessment.existem_recomendacoes_da_saude')} />
|
||||
</div>
|
||||
<BrInput label="Se possui recomendações da saúde" value={formData.student_assessment.se_possui_recomendacoes_da_saude} onInput={(e: any) => handleInputChange('student_assessment.se_possui_recomendacoes_da_saude', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Desenvolvimento do Estudante */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Desenvolvimento do Estudante</h2>
|
||||
|
||||
{/* Função Cognitiva */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Função Cognitiva</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Percepção" value={formData.student_development.funcao_cognitiva.percepcao} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.percepcao', e.target.value)} />
|
||||
<BrInput label="Atenção" value={formData.student_development.funcao_cognitiva.atencao} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.atencao', e.target.value)} />
|
||||
<BrInput label="Memória" value={formData.student_development.funcao_cognitiva.memoria} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.memoria', e.target.value)} />
|
||||
<BrInput label="Linguagem" value={formData.student_development.funcao_cognitiva.linguagem} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.linguagem', e.target.value)} />
|
||||
<BrInput label="Raciocínio lógico" value={formData.student_development.funcao_cognitiva.raciocinio_logico} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.raciocinio_logico', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Função Motora */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Função Motora</h3>
|
||||
<BrInput label="Desenvolvimento e capacidade motora" value={formData.student_development.funcao_motora.desenvolvimento_e_capacidade_motora} onInput={(e: any) => handleInputChange('student_development.funcao_motora.desenvolvimento_e_capacidade_motora', e.target.value)} />
|
||||
</div>
|
||||
|
||||
{/* Função Pessoal Social */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Função Pessoal Social</h3>
|
||||
<BrInput label="Área emocional, afetiva e social" value={formData.student_development.funcao_pressoal_social.area_emocional_afetiva_social} onInput={(e: any) => handleInputChange('student_development.funcao_pressoal_social.area_emocional_afetiva_social', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Botões */}
|
||||
<div className="flex justify-center gap-4 mt-8">
|
||||
<button className="bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded-full" onClick={() => router.push(`/anamnese?email=${email}&nome=${nome}`)}>
|
||||
Cancelar
|
||||
</button>
|
||||
<button className="bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-full" onClick={handleEdit}>
|
||||
Salvar Alterações
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
// Provenance: jardimdesoftware/edutrace (vuln).
|
||||
// repo: jardimdesoftware/edutrace
|
||||
// commit: c4dc6ddcc5492c77c8a5ad7369c87dea29c001fd
|
||||
// parent: c4dc6ddcc5492c77c8a5ad7369c87dea29c001fd
|
||||
// commit_url: https://github.com/jardimdesoftware/edutrace/commit/ee7ba25fb23ea89cc1b67549cb5e32c8ead92739
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: handleInputChange
|
||||
// relpath: front/src/app/editar-anamnese/page.tsx
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function AnamnesePage() {
|
||||
const searchParams = useSearchParams();
|
||||
const email = searchParams.get("email");
|
||||
const nome = searchParams.get("nome");
|
||||
|
||||
const { loading } = useAuth();
|
||||
const router = useRouter();
|
||||
|
||||
const [anamnesis, setAnamnesis] = useState<AnamnesisData | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const [formData, setFormData] = useState<AnamnesisData>(initialAnamnesisState);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const token = decodeToken();
|
||||
if (!token) {
|
||||
router.push('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
const isStudent = token.id_level === ESTUDANTE;
|
||||
|
||||
if (token.id_level === PROFISSIONAL_EDUCACAO || isStudent) {
|
||||
router.push(`/anamnese${email ? `?email=${email}&nome=${nome}` : ''}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const target = isStudent ? token.email : email;
|
||||
|
||||
if (target) {
|
||||
const data = await getAnamneseByEmail(target);
|
||||
setAnamnesis(data);
|
||||
setFormData(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Anamnese não encontrada, iniciando modo de criação.", error);
|
||||
setAnamnesis(null);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
fetchData();
|
||||
}, [email, nome, router]);
|
||||
|
||||
|
||||
const handleInputChange = (name: string, value: string) => {
|
||||
const keys = name.split('.');
|
||||
|
||||
setFormData(prevData => {
|
||||
const newData = JSON.parse(JSON.stringify(prevData));
|
||||
let current = newData;
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
current = current[keys[i]];
|
||||
}
|
||||
current[keys[keys.length - 1]] = value;
|
||||
return newData;
|
||||
});
|
||||
};
|
||||
|
||||
const handleCheckboxClick = (name: string) => {
|
||||
const keys = name.split('.');
|
||||
|
||||
setFormData(prevData => {
|
||||
// Criar uma cópia profunda para segurança
|
||||
const newData = JSON.parse(JSON.stringify(prevData));
|
||||
|
||||
let currentSection = newData;
|
||||
// Navega até o penúltimo nível do objeto
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
currentSection = currentSection[keys[i]];
|
||||
}
|
||||
|
||||
const finalKey = keys[keys.length - 1];
|
||||
const currentValue = currentSection[finalKey];
|
||||
|
||||
// Inverte o valor booleano atual
|
||||
currentSection[finalKey] = !currentValue;
|
||||
|
||||
return newData;
|
||||
});
|
||||
};
|
||||
|
||||
const handleEdit = async () => {
|
||||
if (!email) {
|
||||
alert("Email do estudante não encontrado para editar anamnese.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dadosAtualizados = { ...formData };
|
||||
await patchAnamnesis(dadosAtualizados, email);
|
||||
alert("Anamnese atualizada com sucesso!");
|
||||
router.push(`/estudantes/visualizar?email=${email}&nome=${nome}`);
|
||||
} catch (error) {
|
||||
console.error("Erro ao atualizar Anamnese: ", error);
|
||||
alert("Falha ao atualizar Anamnese. Verifique o console para mais detalhes.");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (isLoading || loading) {
|
||||
return <h1>Carregando...</h1>; //ADICIONAR COMPONENTE DE LOADING
|
||||
}
|
||||
|
||||
if (anamnesis === null) {
|
||||
return (
|
||||
<AppLayout
|
||||
>
|
||||
<div className="p-6 text-center">
|
||||
<h2 className="text-xl font-bold text-green-700">O estudante ainda não possui uma Anamnese cadastrada</h2>
|
||||
<button className="mt-6 bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-full" onClick={() => router.push(`/estudantes/visualizar?email=${email}&nome=${nome}`)}>
|
||||
Voltar
|
||||
</button>
|
||||
</div>
|
||||
</AppLayout>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<AppLayout
|
||||
>
|
||||
<div className="p-6 space-y-8 w-full">
|
||||
<h1 className="text-3xl font-bold text-gray-800">Editar Anamnese</h1>
|
||||
|
||||
{/* Identificação */}
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold mb-4">Identificação</h2>
|
||||
<div className="grid md:grid-cols-4 gap-4">
|
||||
<BrInput label="Nome da unidade plena" value={formData.identification.nome_unidade_plena} onInput={(e: any) => handleInputChange('identification.nome_unidade_plena', e.target.value)} />
|
||||
<BrInput label="Nome completo" value={formData.identification.nome_completo} onInput={(e: any) => handleInputChange('identification.nome_completo', e.target.value)} />
|
||||
<BrInput label="Data de Nascimento" value={formData.identification.data_de_nascimento} onInput={(e: any) => handleInputChange('identification.data_de_nascimento', e.target.value)} />
|
||||
<BrInput label="Endereço" value={formData.identification.endereco} onInput={(e: any) => handleInputChange('identification.endereco', e.target.value)} />
|
||||
<BrInput label="Bairro" value={formData.identification.bairo} onInput={(e: any) => handleInputChange('identification.bairo', e.target.value)} />
|
||||
<BrInput label="CEP" value={formData.identification.cep} onInput={(e: any) => handleInputChange('identification.cep', e.target.value)} />
|
||||
<BrInput label="Município" value={formData.identification.municipio} onInput={(e: any) => handleInputChange('identification.municipio', e.target.value)} />
|
||||
<BrInput label="Curso" value={formData.identification.curso} onInput={(e: any) => handleInputChange('identification.curso', e.target.value)} />
|
||||
<BrInput label="Série de escolaridade atual" value={formData.identification.serie_de_escolaridade_atual} onInput={(e: any) => handleInputChange('identification.serie_de_escolaridade_atual', e.target.value)} />
|
||||
<BrInput label="Turma" value={formData.identification.turma} onInput={(e: any) => handleInputChange('identification.turma', e.target.value)} />
|
||||
<BrInput label="Idade que iniciou os estudos" value={formData.identification.idade_iniciou_estudos} onInput={(e: any) => handleInputChange('identification.idade_iniciou_estudos', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Dados Familiares */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Dados familiares</h2>
|
||||
<div className="grid md:grid-cols-4 gap-4">
|
||||
<BrInput label="Nome do pai" value={formData.family_data.nome_pai} onInput={(e: any) => handleInputChange('family_data.nome_pai', e.target.value)} />
|
||||
<BrInput label="Profissão do pai" value={formData.family_data.profissao_pai} onInput={(e: any) => handleInputChange('family_data.profissao_pai', e.target.value)} />
|
||||
<BrInput label="Escolaridade do pai" value={formData.family_data.escolaridade_pai} onInput={(e: any) => handleInputChange('family_data.escolaridade_pai', e.target.value)} />
|
||||
<BrInput label="Idade do pai" value={formData.family_data.idade_pai} onInput={(e: any) => handleInputChange('family_data.idade_pai', e.target.value)} />
|
||||
<BrInput label="Nome da mãe" value={formData.family_data.nome_mae} onInput={(e: any) => handleInputChange('family_data.nome_mae', e.target.value)} />
|
||||
<BrInput label="Profissão da mãe" value={formData.family_data.profissao_mae} onInput={(e: any) => handleInputChange('family_data.profissao_mae', e.target.value)} />
|
||||
<BrInput label="Escolaridade da mãe" value={formData.family_data.escolaridade_mae} onInput={(e: any) => handleInputChange('family_data.escolaridade_mae', e.target.value)} />
|
||||
<BrInput label="Idade da mãe" value={formData.family_data.idade_mae} onInput={(e: any) => handleInputChange('family_data.idade_mae', e.target.value)} />
|
||||
<BrInput label="Outros filhos" value={formData.family_data.outros_filhos} onInput={(e: any) => handleInputChange('family_data.outros_filhos', e.target.value)} />
|
||||
</div>
|
||||
<div className="mt-4 space-y-2">
|
||||
<label className="text-sm font-medium text-black">União dos Pais</label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Casados" checked={formData.family_data.uniao_pais.casados} onClick={() => handleCheckboxClick('family_data.uniao_pais.casados')} />
|
||||
<BrCheckbox name="" label="Separados" checked={formData.family_data.uniao_pais.separados} onClick={() => handleCheckboxClick('family_data.uniao_pais.separados')} />
|
||||
<BrCheckbox name="" label="Separados como uma nova estrutura familiar" checked={formData.family_data.uniao_pais.separados_como_nova_estrutura_familia} onClick={() => handleCheckboxClick('family_data.uniao_pais.separados_como_nova_estrutura_familia')} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 space-y-2">
|
||||
<label className="text-sm font-medium text-black">Pais</label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Biológico" checked={formData.family_data.pais.biologico} onClick={() => handleCheckboxClick('family_data.pais.biologico')} />
|
||||
<BrCheckbox name="" label="Adotivo" checked={formData.family_data.pais.adotivo} onClick={() => handleCheckboxClick('family_data.pais.adotivo')} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Em caso de separação, o estudante vive com quem?" value={formData.family_data.estudante_reside_com_quem} onInput={(e: any) => handleInputChange('family_data.estudante_reside_com_quem', e.target.value)} />
|
||||
<BrInput label="Reação do estudante à situação" value={formData.family_data.reacao_estudante_situacao} onInput={(e: any) => handleInputChange('family_data.reacao_estudante_situacao', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Condições familiares do estudante */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Condições familiares do estudante</h2>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Condições de moradia</p>
|
||||
<div className="flex space-x-3">
|
||||
<BrCheckbox name="" label="Taipa" checked={formData.family_conditions.moradia.taipa} onClick={() => handleCheckboxClick('family_conditions.moradia.taipa')} />
|
||||
<BrCheckbox name="" label="Alvenaria" checked={formData.family_conditions.moradia.alvenaria} onClick={() => handleCheckboxClick('family_conditions.moradia.alvenaria')} />
|
||||
<BrCheckbox name="" label="Palafita" checked={formData.family_conditions.moradia.palafita} onClick={() => handleCheckboxClick('family_conditions.moradia.palafita')} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Convívio familiar</p>
|
||||
<div className="flex space-x-3">
|
||||
<BrCheckbox name="" label="Excelente" checked={formData.family_conditions.convivio_familiar.excelente} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.excelente')} />
|
||||
<BrCheckbox name="" label="Bom" checked={formData.family_conditions.convivio_familiar.bom} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.bom')} />
|
||||
<BrCheckbox name="" label="Problemático" checked={formData.family_conditions.convivio_familiar.problematico} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.problematico')} />
|
||||
<BrCheckbox name="" label="Precário" checked={formData.family_conditions.convivio_familiar.precario} onClick={() => handleCheckboxClick('family_conditions.convivio_familiar.precario')} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Qualidade de comunicação</p>
|
||||
<div className="flex space-x-3">
|
||||
<BrCheckbox name="" label="Excelente" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.execelente} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.execelente')} />
|
||||
<BrCheckbox name="" label="Boa" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.boa} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.boa')} />
|
||||
<BrCheckbox name="" label="Ruim" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.ruim} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.ruim')} />
|
||||
<BrCheckbox name="" label="Péssima" checked={formData.family_conditions.qualidade_comunicacao_com_estudante.pessima} onClick={() => handleCheckboxClick('family_conditions.qualidade_comunicacao_com_estudante.pessima')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-4 mt-6">
|
||||
<BrInput label="Que medidas disciplinares normalmente são usadas com o estudante" value={formData.family_conditions.medidas_disciplinares_com_estudante} onInput={(e: any) => handleInputChange('family_conditions.medidas_disciplinares_com_estudante', e.target.value)} />
|
||||
<BrInput label="Quem as usa" value={formData.family_conditions.quem_usa_medidas_disciplinares} onInput={(e: any) => handleInputChange('family_conditions.quem_usa_medidas_disciplinares', e.target.value)} />
|
||||
<BrInput label="Quais as reações do estudante frente a essas medidas" value={formData.family_conditions.reacao_estudante_frente_medidas} onInput={(e: any) => handleInputChange('family_conditions.reacao_estudante_frente_medidas', e.target.value)} />
|
||||
<BrInput label="Como reage quando contrariado" value={formData.family_conditions.reacao_contrariado} onInput={(e: any) => handleInputChange('family_conditions.reacao_contrariado', e.target.value)} />
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<p className="text-sm font-medium mb-2">Condições do ambiente familiar para a aprendizagem escolar</p>
|
||||
<BrInput label="Condição" value={formData.family_conditions.condicao_ambiente_familiar_aprendizagem_escolar} onInput={(e: any) => handleInputChange('family_conditions.condicao_ambiente_familiar_aprendizagem_escolar', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Histórico da Mãe */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Histórico da Mãe</h2>
|
||||
|
||||
{/* Gestação */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Gestação</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<BrInput label="Transfusão sanguínea na gravidez" value={formData.mother_background.gestacao.transfusao_sanguinea_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.transfusao_sanguinea_gravidez', e.target.value)} />
|
||||
<BrInput label="Quando sentiu movimento da criança" value={formData.mother_background.gestacao.quando_sentiu_movimento_da_crianca} onInput={(e: any) => handleInputChange('mother_background.gestacao.quando_sentiu_movimento_da_crianca', e.target.value)} />
|
||||
<BrInput label="Levou tombo durante a gravidez" value={formData.mother_background.gestacao.levou_tombo_durante_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.levou_tombo_durante_gravidez', e.target.value)} />
|
||||
<BrInput label="Doença na gestação" value={formData.mother_background.gestacao.doenca_na_gestacao} onInput={(e: any) => handleInputChange('mother_background.gestacao.doenca_na_gestacao', e.target.value)} />
|
||||
<BrInput label="Condição de saúde da mãe na gravidez" value={formData.mother_background.gestacao.condicao_saude_da_mae_na_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.condicao_saude_da_mae_na_gravidez', e.target.value)} />
|
||||
<BrInput label="Episódio marcante na gravidez" value={formData.mother_background.gestacao.episodio_marcante_gravidez} onInput={(e: any) => handleInputChange('mother_background.gestacao.episodio_marcante_gravidez', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Condições de Nascimento */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Condições de Nascimento</h3>
|
||||
<div className="grid md:grid-cols-4 gap-4">
|
||||
<BrInput label="Nasceu com quantos meses" value={formData.mother_background.condicoes_nascimento.nasceu_quantos_meses} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.nasceu_quantos_meses', e.target.value)} />
|
||||
<BrInput label="Nasceu com quantos quilos" value={formData.mother_background.condicoes_nascimento.nasceu_quantos_quilos} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.nasceu_quantos_quilos', e.target.value)} />
|
||||
<BrInput label="Nasceu com qual comprimento" value={formData.mother_background.condicoes_nascimento.nasceu_com_qual_comprimento} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.nasceu_com_qual_comprimento', e.target.value)} />
|
||||
<BrInput label="Desenvolvimento do parto" value={formData.mother_background.condicoes_nascimento.desenvolvimento_parto} onInput={(e: any) => handleInputChange('mother_background.condicoes_nascimento.desenvolvimento_parto', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Primeiras Reações */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Primeiras Reações</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<BrInput label="Chorou" value={formData.mother_background.primeiras_reacoes.chorou} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.chorou', e.target.value)} />
|
||||
<BrInput label="Ficou vermelho demais" value={formData.mother_background.primeiras_reacoes.ficou_vermelho_demais} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.ficou_vermelho_demais', e.target.value)} />
|
||||
<BrInput label="Ficou vermelho por quanto tempo" value={formData.mother_background.primeiras_reacoes.ficou_vermelho_por_quanto_tempo} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.ficou_vermelho_por_quanto_tempo', e.target.value)} />
|
||||
<BrInput label="Precisou de oxigênio" value={formData.mother_background.primeiras_reacoes.precisou_de_oxigenio} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.precisou_de_oxigenio', e.target.value)} />
|
||||
<BrInput label="Ficou ictérico" value={formData.mother_background.primeiras_reacoes.ficou_icterico} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.ficou_icterico', e.target.value)} />
|
||||
<BrInput label="Como era quando bebê" value={formData.mother_background.primeiras_reacoes.como_era_quando_bebe} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.como_era_quando_bebe', e.target.value)} />
|
||||
<BrInput label="Qual idade afirmou a cabeça" value={formData.mother_background.primeiras_reacoes.qual_idade_afirmou_cabeca} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_afirmou_cabeca', e.target.value)} />
|
||||
<BrInput label="Qual idade sentou sem apoio" value={formData.mother_background.primeiras_reacoes.qual_idade_sentou_sem_apoio} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_sentou_sem_apoio', e.target.value)} />
|
||||
<BrInput label="Qual idade engatinhou" value={formData.mother_background.primeiras_reacoes.qual_idade_engatinhou} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_engatinhou', e.target.value)} />
|
||||
<BrInput label="Qual idade ficou de pé" value={formData.mother_background.primeiras_reacoes.qual_idade_ficou_de_pe} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_ficou_de_pe', e.target.value)} />
|
||||
<BrInput label="Qual idade andou" value={formData.mother_background.primeiras_reacoes.qual_idade_andou} onInput={(e: any) => handleInputChange('mother_background.primeiras_reacoes.qual_idade_andou', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Linguagem Verbal (3 anos) */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Linguagem Verbal (3 anos)</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Balbuciou" checked={formData.verbal_language_three_years.balbuciou} onClick={() => handleCheckboxClick('verbal_language_three_years.balbuciou')} />
|
||||
<BrCheckbox name="" label="Trocou letras" checked={formData.verbal_language_three_years.trocou_letras} onClick={() => handleCheckboxClick('verbal_language_three_years.trocou_letras')} />
|
||||
<BrCheckbox name="" label="Gaguejou" checked={formData.verbal_language_three_years.gaguejou} onClick={() => handleCheckboxClick('verbal_language_three_years.gaguejou')} />
|
||||
</div>
|
||||
<BrInput label="Primeiras expressões" value={formData.verbal_language_three_years.primeiras_expressoes} onInput={(e: any) => handleInputChange('verbal_language_three_years.primeiras_expressoes', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Desenvolvimento */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Desenvolvimento</h2>
|
||||
|
||||
{/* Saúde */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Saúde</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Sofreu acidente ou fez cirurgia" value={formData.development.saude.sofreu_acidente_ou_fez_cirurgia} onInput={(e: any) => handleInputChange('development.saude.sofreu_acidente_ou_fez_cirurgia', e.target.value)} />
|
||||
<BrInput label="Possui alergia" value={formData.development.saude.possui_alergia} onInput={(e: any) => handleInputChange('development.saude.possui_alergia', e.target.value)} />
|
||||
<BrInput label="Possui bronquite ou asma" value={formData.development.saude.possui_bronquite_ou_asma} onInput={(e: any) => handleInputChange('development.saude.possui_bronquite_ou_asma', e.target.value)} />
|
||||
<BrInput label="Possui problema de visão ou audição" value={formData.development.saude.possui_problema_visao_audicao} onInput={(e: any) => handleInputChange('development.saude.possui_problema_visao_audicao', e.target.value)} />
|
||||
<BrInput label="Já desmaiou" value={formData.development.saude.ja_desmaiou} onInput={(e: any) => handleInputChange('development.saude.ja_desmaiou', e.target.value)} />
|
||||
<BrInput label="Quando desmaiou" value={formData.development.saude.quando_desmaiou} onInput={(e: any) => handleInputChange('development.saude.quando_desmaiou', e.target.value)} />
|
||||
<BrInput label="Teve ou tem convulsões" value={formData.development.saude.teve_ou_tem_convulsoes} onInput={(e: any) => handleInputChange('development.saude.teve_ou_tem_convulsoes', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Alimentação */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Alimentação</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Foi amamentada" value={formData.development.alimentacao.foi_amamentada} onInput={(e: any) => handleInputChange('development.alimentacao.foi_amamentada', e.target.value)} />
|
||||
<BrInput label="Foi amamentada até quando" value={formData.development.alimentacao.foi_amementada_ate_quando} onInput={(e: any) => handleInputChange('development.alimentacao.foi_amementada_ate_quando', e.target.value)} />
|
||||
<BrInput label="Como é sua alimentação" value={formData.development.alimentacao.como_e_sua_alimentacao} onInput={(e: any) => handleInputChange('development.alimentacao.como_e_sua_alimentacao', e.target.value)} />
|
||||
<BrInput label="Foi forçado a se alimentar" value={formData.development.alimentacao.foi_forcado_se_alimentar} onInput={(e: any) => handleInputChange('development.alimentacao.foi_forcado_se_alimentar', e.target.value)} />
|
||||
<BrInput label="Recebe ajuda na alimentação" value={formData.development.alimentacao.recebe_ajuda_na_alimentacao} onInput={(e: any) => handleInputChange('development.alimentacao.recebe_ajuda_na_alimentacao', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sono */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Sono</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Dorme bem" checked={formData.development.sono.dorme_bem} onClick={() => handleCheckboxClick('development.sono.dorme_bem')} />
|
||||
<BrCheckbox name="" label="Dorme separado dos pais" checked={formData.development.sono.dorme_separado_dos_pais} onClick={() => handleCheckboxClick('development.sono.dorme_separado_dos_pais')} />
|
||||
</div>
|
||||
<BrInput label="Com quem dorme" value={formData.development.sono.com_quem_dorme} onInput={(e: any) => handleInputChange('development.sono.com_quem_dorme', e.target.value)} />
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<p className="text-sm font-medium mb-2">Tipo de sono</p>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Agitado" checked={formData.development.sono.sono.agitado} onClick={() => handleCheckboxClick('development.sono.sono.agitado')} />
|
||||
<BrCheckbox name="" label="Tranquilo" checked={formData.development.sono.sono.tranquilo} onClick={() => handleCheckboxClick('development.sono.sono.tranquilo')} />
|
||||
<BrCheckbox name="" label="Fala dormindo" checked={formData.development.sono.sono.fala_dormindo} onClick={() => handleCheckboxClick('development.sono.sono.fala_dormindo')} />
|
||||
<BrCheckbox name="" label="Sonâmbulo" checked={formData.development.sono.sono.sonambulo} onClick={() => handleCheckboxClick('development.sono.sono.sonambulo')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Informações Escolares */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Informações Escolares</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Histórico escolar comum - antecedentes relevantes" value={formData.school_information.historico_escolar_comum_antecedentes_relevantes} onInput={(e: any) => handleInputChange('school_information.historico_escolar_comum_antecedentes_relevantes', e.target.value)} />
|
||||
<BrInput label="Histórico escolar especial - antecedentes relevantes" value={formData.school_information.historico_escolar_especial_antecedentes_relevantes} onInput={(e: any) => handleInputChange('school_information.historico_escolar_especial_antecedentes_relevantes', e.target.value)} />
|
||||
<BrInput label="Deficiência apresentada pelo estudante" value={formData.school_information.deficiencia_apresentada_estudante} onInput={(e: any) => handleInputChange('school_information.deficiencia_apresentada_estudante', e.target.value)} />
|
||||
<BrInput label="Foi retido alguma vez" value={formData.school_information.retido_alguma_vez} onInput={(e: any) => handleInputChange('school_information.retido_alguma_vez', e.target.value)} />
|
||||
<BrInput label="Gosta de ir à escola" value={formData.school_information.gosta_de_ir_escola} onInput={(e: any) => handleInputChange('school_information.gosta_de_ir_escola', e.target.value)} />
|
||||
<BrInput label="É bem aceito pelos amigos" value={formData.school_information.bem_aceito_pelos_amigous} onInput={(e: any) => handleInputChange('school_information.bem_aceito_pelos_amigous', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Sexualidade */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Sexualidade</h2>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<BrCheckbox name="" label="Explanação sexual" checked={formData.sexuality.explanacao_sexual} onClick={() => handleCheckboxClick('sexuality.explanacao_sexual')} />
|
||||
<BrCheckbox name="" label="Curiosidade sexual" checked={formData.sexuality.curiosidade_sexual} onClick={() => handleCheckboxClick('sexuality.curiosidade_sexual')} />
|
||||
<BrCheckbox name="" label="Conversa com pais sobre sexualidade" checked={formData.sexuality.conversa_com_pais_sobre_sexualidade} onClick={() => handleCheckboxClick('sexuality.conversa_com_pais_sobre_sexualidade')} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Avaliação do Estudante */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Avaliação do Estudante</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Estudante apresenta outro tipo de deficiência" value={formData.student_assessment.estudante_apresenta_outro_tipo_deficiencia} onInput={(e: any) => handleInputChange('student_assessment.estudante_apresenta_outro_tipo_deficiencia', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Apresenta DA/DF/DI/PC/TGD" checked={formData.student_assessment.apresenta_da_df_di_pc_tgd} onClick={() => handleCheckboxClick('student_assessment.apresenta_da_df_di_pc_tgd')} />
|
||||
</div>
|
||||
<BrInput label="Se sim, data e resultado do diagnóstico" value={formData.student_assessment.se_sim_data_e_resultado_diagnostico} onInput={(e: any) => handleInputChange('student_assessment.se_sim_data_e_resultado_diagnostico', e.target.value)} />
|
||||
<BrInput label="Se não, situação quanto ao diagnóstico - tem outras dificuldades" value={formData.student_assessment.se_não_situacao_quanto_diagnostico_tem_outras_dificuldades} onInput={(e: any) => handleInputChange('student_assessment.se_não_situacao_quanto_diagnostico_tem_outras_dificuldades', e.target.value)} />
|
||||
<BrInput label="Se tem outras dificuldades" value={formData.student_assessment.se_tem_outras_dificuldades} onInput={(e: any) => handleInputChange('student_assessment.se_tem_outras_dificuldades', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Usa medicamentos controlados" checked={formData.student_assessment.usa_medicamentos_controlados} onClick={() => handleCheckboxClick('student_assessment.usa_medicamentos_controlados')} />
|
||||
</div>
|
||||
<BrInput label="Usa quais medicamentos" value={formData.student_assessment.usa_quais_medicamentos} onInput={(e: any) => handleInputChange('student_assessment.usa_quais_medicamentos', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Medicamento interfere na aprendizagem" checked={formData.student_assessment.medicamento_interfere_aprendizagem} onClick={() => handleCheckboxClick('student_assessment.medicamento_interfere_aprendizagem')} />
|
||||
</div>
|
||||
<BrInput label="Se interfere na aprendizagem" value={formData.student_assessment.se_intefere_aprendizagem} onInput={(e: any) => handleInputChange('student_assessment.se_intefere_aprendizagem', e.target.value)} />
|
||||
<div className="space-y-2">
|
||||
<BrCheckbox name="" label="Existem recomendações da saúde" checked={formData.student_assessment.existem_recomendacoes_da_saude} onClick={() => handleCheckboxClick('student_assessment.existem_recomendacoes_da_saude')} />
|
||||
</div>
|
||||
<BrInput label="Se possui recomendações da saúde" value={formData.student_assessment.se_possui_recomendacoes_da_saude} onInput={(e: any) => handleInputChange('student_assessment.se_possui_recomendacoes_da_saude', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Desenvolvimento do Estudante */}
|
||||
<section className="border-t pt-6 mt-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Desenvolvimento do Estudante</h2>
|
||||
|
||||
{/* Função Cognitiva */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Função Cognitiva</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<BrInput label="Percepção" value={formData.student_development.funcao_cognitiva.percepcao} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.percepcao', e.target.value)} />
|
||||
<BrInput label="Atenção" value={formData.student_development.funcao_cognitiva.atencao} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.atencao', e.target.value)} />
|
||||
<BrInput label="Memória" value={formData.student_development.funcao_cognitiva.memoria} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.memoria', e.target.value)} />
|
||||
<BrInput label="Linguagem" value={formData.student_development.funcao_cognitiva.linguagem} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.linguagem', e.target.value)} />
|
||||
<BrInput label="Raciocínio lógico" value={formData.student_development.funcao_cognitiva.raciocinio_logico} onInput={(e: any) => handleInputChange('student_development.funcao_cognitiva.raciocinio_logico', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Função Motora */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Função Motora</h3>
|
||||
<BrInput label="Desenvolvimento e capacidade motora" value={formData.student_development.funcao_motora.desenvolvimento_e_capacidade_motora} onInput={(e: any) => handleInputChange('student_development.funcao_motora.desenvolvimento_e_capacidade_motora', e.target.value)} />
|
||||
</div>
|
||||
|
||||
{/* Função Pessoal Social */}
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium mb-3">Função Pessoal Social</h3>
|
||||
<BrInput label="Área emocional, afetiva e social" value={formData.student_development.funcao_pressoal_social.area_emocional_afetiva_social} onInput={(e: any) => handleInputChange('student_development.funcao_pressoal_social.area_emocional_afetiva_social', e.target.value)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Botões */}
|
||||
<div className="flex justify-center gap-4 mt-8">
|
||||
<button className="bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded-full" onClick={() => router.push(`/anamnese?email=${email}&nome=${nome}`)}>
|
||||
Cancelar
|
||||
</button>
|
||||
<button className="bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-full" onClick={handleEdit}>
|
||||
Salvar Alterações
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Provenance: dayflower/etude-lexical-markdown (fixed).
|
||||
// repo: dayflower/etude-lexical-markdown
|
||||
// commit: c61a8bf78fe20d6ae0eab2e4b8b02004508525ed
|
||||
// parent: 0a2184f59e79a04b1365cd49200026e8f2ffdbd5
|
||||
// commit_url: https://github.com/dayflower/etude-lexical-markdown/commit/c61a8bf78fe20d6ae0eab2e4b8b02004508525ed
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: deepMergeInto
|
||||
// relpath: src/config/editorConfig.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function deepMergeInto(
|
||||
target: Record<string, unknown>,
|
||||
source: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
for (const key of Object.keys(source)) {
|
||||
if (FORBIDDEN_KEYS.has(key)) continue;
|
||||
const sourceValue = source[key];
|
||||
if (sourceValue === undefined) continue;
|
||||
if (isPlainObject(sourceValue)) {
|
||||
const targetValue = target[key];
|
||||
const nested = isPlainObject(targetValue) ? targetValue : {};
|
||||
target[key] = deepMergeInto(nested, sourceValue);
|
||||
} else {
|
||||
target[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Provenance: dayflower/etude-lexical-markdown (vuln).
|
||||
// repo: dayflower/etude-lexical-markdown
|
||||
// commit: 0a2184f59e79a04b1365cd49200026e8f2ffdbd5
|
||||
// parent: 0a2184f59e79a04b1365cd49200026e8f2ffdbd5
|
||||
// commit_url: https://github.com/dayflower/etude-lexical-markdown/commit/c61a8bf78fe20d6ae0eab2e4b8b02004508525ed
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: deepMergeInto
|
||||
// relpath: src/config/editorConfig.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function deepMergeInto(
|
||||
target: Record<string, unknown>,
|
||||
source: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
for (const key of Object.keys(source)) {
|
||||
const sourceValue = source[key];
|
||||
if (sourceValue === undefined) continue;
|
||||
if (isPlainObject(sourceValue)) {
|
||||
const targetValue = target[key];
|
||||
const nested = isPlainObject(targetValue) ? targetValue : {};
|
||||
target[key] = deepMergeInto(nested, sourceValue);
|
||||
} else {
|
||||
target[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Provenance: dayflower/etude-lexical-markdown (fixed).
|
||||
// repo: dayflower/etude-lexical-markdown
|
||||
// commit: db4f54b1ab80ad596de6425e84f90aa781c49999
|
||||
// parent: 1c865815d05b072f4973388c3ac66b6696d9efde
|
||||
// commit_url: https://github.com/dayflower/etude-lexical-markdown/commit/db4f54b1ab80ad596de6425e84f90aa781c49999
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: deepMergeInto
|
||||
// relpath: src/config/editorConfig.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function deepMergeInto(
|
||||
target: Record<string, unknown>,
|
||||
source: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
for (const key of Object.keys(source)) {
|
||||
if (isForbiddenKey(key)) continue;
|
||||
const sourceValue = source[key];
|
||||
if (sourceValue === undefined) continue;
|
||||
if (isPlainObject(sourceValue)) {
|
||||
const targetValue = target[key];
|
||||
const nested = isPlainObject(targetValue) ? targetValue : {};
|
||||
target[key] = deepMergeInto(nested, sourceValue);
|
||||
} else {
|
||||
target[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Provenance: dayflower/etude-lexical-markdown (vuln).
|
||||
// repo: dayflower/etude-lexical-markdown
|
||||
// commit: 1c865815d05b072f4973388c3ac66b6696d9efde
|
||||
// parent: 1c865815d05b072f4973388c3ac66b6696d9efde
|
||||
// commit_url: https://github.com/dayflower/etude-lexical-markdown/commit/db4f54b1ab80ad596de6425e84f90aa781c49999
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: deepMergeInto
|
||||
// relpath: src/config/editorConfig.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function deepMergeInto(
|
||||
target: Record<string, unknown>,
|
||||
source: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
for (const key of Object.keys(source)) {
|
||||
if (FORBIDDEN_KEYS.has(key)) continue;
|
||||
const sourceValue = source[key];
|
||||
if (sourceValue === undefined) continue;
|
||||
if (isPlainObject(sourceValue)) {
|
||||
const targetValue = target[key];
|
||||
const nested = isPlainObject(targetValue) ? targetValue : {};
|
||||
target[key] = deepMergeInto(nested, sourceValue);
|
||||
} else {
|
||||
target[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
// Provenance: navaneethbv/market-cap (fixed).
|
||||
// repo: navaneethbv/market-cap
|
||||
// commit: 4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6
|
||||
// parent: fec6f024ce72c9c47b61cbac6ce7a35cb2280602
|
||||
// commit_url: https://github.com/navaneethbv/market-cap/commit/4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: GET
|
||||
// relpath: app/auth/confirm/route.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const token_hash = searchParams.get("token_hash");
|
||||
const type = searchParams.get("type") as EmailOtpType | null;
|
||||
const nextParam = searchParams.get("next") ?? "/";
|
||||
// Only allow same-origin relative paths to prevent open redirects
|
||||
const next =
|
||||
nextParam.startsWith("/") && !nextParam.startsWith("//") ? nextParam : "/";
|
||||
|
||||
if (token_hash && type) {
|
||||
const supabase = await createClient();
|
||||
const { error } = await supabase.auth.verifyOtp({ type, token_hash });
|
||||
if (!error) {
|
||||
return NextResponse.redirect(new URL(next, request.url));
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.redirect(new URL("/login?error=confirm", request.url));
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Provenance: navaneethbv/market-cap (vuln).
|
||||
// repo: navaneethbv/market-cap
|
||||
// commit: fec6f024ce72c9c47b61cbac6ce7a35cb2280602
|
||||
// parent: fec6f024ce72c9c47b61cbac6ce7a35cb2280602
|
||||
// commit_url: https://github.com/navaneethbv/market-cap/commit/4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: GET
|
||||
// relpath: app/auth/confirm/route.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const token_hash = searchParams.get("token_hash");
|
||||
const type = searchParams.get("type") as EmailOtpType | null;
|
||||
const next = searchParams.get("next") ?? "/";
|
||||
|
||||
if (token_hash && type) {
|
||||
const supabase = await createClient();
|
||||
const { error } = await supabase.auth.verifyOtp({ type, token_hash });
|
||||
if (!error) {
|
||||
return NextResponse.redirect(new URL(next, request.url));
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.redirect(new URL("/login?error=confirm", request.url));
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Provenance: alexshao3/melodix (fixed).
|
||||
// repo: alexshao3/melodix
|
||||
// commit: 089931ef71ea1e5b7586520baf1a5498e2f05b13
|
||||
// parent: c074fc7413338aefcbea3170ef4d3ba486a8a4b7
|
||||
// commit_url: https://github.com/alexshao3/melodix/commit/089931ef71ea1e5b7586520baf1a5498e2f05b13
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: PlayerProvider
|
||||
// relpath: apps/miniapp/src/components/PlayerProvider.tsx
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export function PlayerProvider({ children }: { children: React.ReactNode }) {
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||
const [currentTrack, setCurrentTrack] = useState<Track | null>(null);
|
||||
const [queue, setQueue] = useState<Track[]>([]);
|
||||
const [history, setHistory] = useState<Track[]>([]);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const [position, setPosition] = useState(0);
|
||||
const [duration, setDuration] = useState(0);
|
||||
const handleEndedRef = useRef<() => void>(() => {});
|
||||
|
||||
useEffect(() => {
|
||||
const a = new Audio();
|
||||
a.preload = 'metadata';
|
||||
audioRef.current = a;
|
||||
const t = () => setPosition(a.currentTime);
|
||||
const l = () => setDuration(a.duration || 0);
|
||||
const p = () => setIsPlaying(true);
|
||||
const ps = () => setIsPlaying(false);
|
||||
const e = () => handleEndedRef.current?.();
|
||||
a.addEventListener('timeupdate', t);
|
||||
a.addEventListener('loadedmetadata', l);
|
||||
a.addEventListener('play', p);
|
||||
a.addEventListener('pause', ps);
|
||||
a.addEventListener('ended', e);
|
||||
return () => {
|
||||
a.pause();
|
||||
a.removeEventListener('timeupdate', t);
|
||||
a.removeEventListener('loadedmetadata', l);
|
||||
a.removeEventListener('play', p);
|
||||
a.removeEventListener('pause', ps);
|
||||
a.removeEventListener('ended', e);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const playTrack = useCallback((t: Track) => {
|
||||
const a = audioRef.current;
|
||||
if (!a) return;
|
||||
a.src = t.streamUrl ?? t.audioUrl;
|
||||
setCurrentTrack(t);
|
||||
setPosition(0);
|
||||
pushRecentlyPlayed(t);
|
||||
// Best-effort server-side history mirror; `recordPlay` no-ops for guests.
|
||||
void api.recordPlay(t.id);
|
||||
a.play().catch(() => undefined);
|
||||
}, []);
|
||||
|
||||
const play = useCallback(
|
||||
(track: Track, newQueue?: Track[]) => {
|
||||
tgHaptic('light');
|
||||
if (newQueue) {
|
||||
const idx = newQueue.findIndex((t) => t.id === track.id);
|
||||
const upcoming =
|
||||
idx >= 0 ? newQueue.slice(idx + 1) : newQueue.filter((t) => t.id !== track.id);
|
||||
setQueue(upcoming);
|
||||
}
|
||||
if (currentTrack && currentTrack.id !== track.id) {
|
||||
setHistory((h) => [...h.slice(-19), currentTrack]);
|
||||
}
|
||||
playTrack(track);
|
||||
},
|
||||
[currentTrack, playTrack],
|
||||
);
|
||||
|
||||
const toggle = useCallback(() => {
|
||||
const a = audioRef.current;
|
||||
if (!a || !currentTrack) return;
|
||||
tgHaptic('light');
|
||||
if (a.paused) a.play();
|
||||
else a.pause();
|
||||
}, [currentTrack]);
|
||||
|
||||
const next = useCallback(() => {
|
||||
if (queue.length === 0) return;
|
||||
const [head, ...rest] = queue;
|
||||
if (!head) return;
|
||||
if (currentTrack) setHistory((h) => [...h.slice(-19), currentTrack]);
|
||||
setQueue(rest);
|
||||
playTrack(head);
|
||||
}, [queue, currentTrack, playTrack]);
|
||||
|
||||
const prev = useCallback(() => {
|
||||
const a = audioRef.current;
|
||||
if (a && a.currentTime > 3) {
|
||||
a.currentTime = 0;
|
||||
return;
|
||||
}
|
||||
const last = history[history.length - 1];
|
||||
if (!last) {
|
||||
if (a) a.currentTime = 0;
|
||||
return;
|
||||
}
|
||||
setHistory((h) => h.slice(0, -1));
|
||||
if (currentTrack) setQueue((q) => [currentTrack, ...q]);
|
||||
playTrack(last);
|
||||
}, [history, currentTrack, playTrack]);
|
||||
|
||||
useEffect(() => {
|
||||
handleEndedRef.current = () => next();
|
||||
}, [next]);
|
||||
|
||||
const seek = useCallback((s: number) => {
|
||||
const a = audioRef.current;
|
||||
if (!a) return;
|
||||
a.currentTime = s;
|
||||
setPosition(s);
|
||||
}, []);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({ currentTrack, queue, isPlaying, position, duration, play, toggle, next, prev, seek }),
|
||||
[currentTrack, queue, isPlaying, position, duration, play, toggle, next, prev, seek],
|
||||
);
|
||||
|
||||
return <PlayerContext.Provider value={value}>{children}</PlayerContext.Provider>;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
// Provenance: alexshao3/melodix (vuln).
|
||||
// repo: alexshao3/melodix
|
||||
// commit: c074fc7413338aefcbea3170ef4d3ba486a8a4b7
|
||||
// parent: c074fc7413338aefcbea3170ef4d3ba486a8a4b7
|
||||
// commit_url: https://github.com/alexshao3/melodix/commit/089931ef71ea1e5b7586520baf1a5498e2f05b13
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: PlayerProvider
|
||||
// relpath: apps/miniapp/src/components/PlayerProvider.tsx
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export function PlayerProvider({ children }: { children: React.ReactNode }) {
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||
const [currentTrack, setCurrentTrack] = useState<Track | null>(null);
|
||||
const [queue, setQueue] = useState<Track[]>([]);
|
||||
const [history, setHistory] = useState<Track[]>([]);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const [position, setPosition] = useState(0);
|
||||
const [duration, setDuration] = useState(0);
|
||||
const handleEndedRef = useRef<() => void>(() => {});
|
||||
|
||||
useEffect(() => {
|
||||
const a = new Audio();
|
||||
a.crossOrigin = 'anonymous';
|
||||
a.preload = 'metadata';
|
||||
audioRef.current = a;
|
||||
const t = () => setPosition(a.currentTime);
|
||||
const l = () => setDuration(a.duration || 0);
|
||||
const p = () => setIsPlaying(true);
|
||||
const ps = () => setIsPlaying(false);
|
||||
const e = () => handleEndedRef.current?.();
|
||||
a.addEventListener('timeupdate', t);
|
||||
a.addEventListener('loadedmetadata', l);
|
||||
a.addEventListener('play', p);
|
||||
a.addEventListener('pause', ps);
|
||||
a.addEventListener('ended', e);
|
||||
return () => {
|
||||
a.pause();
|
||||
a.removeEventListener('timeupdate', t);
|
||||
a.removeEventListener('loadedmetadata', l);
|
||||
a.removeEventListener('play', p);
|
||||
a.removeEventListener('pause', ps);
|
||||
a.removeEventListener('ended', e);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const playTrack = useCallback((t: Track) => {
|
||||
const a = audioRef.current;
|
||||
if (!a) return;
|
||||
a.src = t.streamUrl ?? t.audioUrl;
|
||||
setCurrentTrack(t);
|
||||
setPosition(0);
|
||||
pushRecentlyPlayed(t);
|
||||
// Best-effort server-side history mirror; `recordPlay` no-ops for guests.
|
||||
void api.recordPlay(t.id);
|
||||
a.play().catch(() => undefined);
|
||||
}, []);
|
||||
|
||||
const play = useCallback(
|
||||
(track: Track, newQueue?: Track[]) => {
|
||||
tgHaptic('light');
|
||||
if (newQueue) {
|
||||
const idx = newQueue.findIndex((t) => t.id === track.id);
|
||||
const upcoming =
|
||||
idx >= 0 ? newQueue.slice(idx + 1) : newQueue.filter((t) => t.id !== track.id);
|
||||
setQueue(upcoming);
|
||||
}
|
||||
if (currentTrack && currentTrack.id !== track.id) {
|
||||
setHistory((h) => [...h.slice(-19), currentTrack]);
|
||||
}
|
||||
playTrack(track);
|
||||
},
|
||||
[currentTrack, playTrack],
|
||||
);
|
||||
|
||||
const toggle = useCallback(() => {
|
||||
const a = audioRef.current;
|
||||
if (!a || !currentTrack) return;
|
||||
tgHaptic('light');
|
||||
if (a.paused) a.play();
|
||||
else a.pause();
|
||||
}, [currentTrack]);
|
||||
|
||||
const next = useCallback(() => {
|
||||
if (queue.length === 0) return;
|
||||
const [head, ...rest] = queue;
|
||||
if (!head) return;
|
||||
if (currentTrack) setHistory((h) => [...h.slice(-19), currentTrack]);
|
||||
setQueue(rest);
|
||||
playTrack(head);
|
||||
}, [queue, currentTrack, playTrack]);
|
||||
|
||||
const prev = useCallback(() => {
|
||||
const a = audioRef.current;
|
||||
if (a && a.currentTime > 3) {
|
||||
a.currentTime = 0;
|
||||
return;
|
||||
}
|
||||
const last = history[history.length - 1];
|
||||
if (!last) {
|
||||
if (a) a.currentTime = 0;
|
||||
return;
|
||||
}
|
||||
setHistory((h) => h.slice(0, -1));
|
||||
if (currentTrack) setQueue((q) => [currentTrack, ...q]);
|
||||
playTrack(last);
|
||||
}, [history, currentTrack, playTrack]);
|
||||
|
||||
useEffect(() => {
|
||||
handleEndedRef.current = () => next();
|
||||
}, [next]);
|
||||
|
||||
const seek = useCallback((s: number) => {
|
||||
const a = audioRef.current;
|
||||
if (!a) return;
|
||||
a.currentTime = s;
|
||||
setPosition(s);
|
||||
}, []);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({ currentTrack, queue, isPlaying, position, duration, play, toggle, next, prev, seek }),
|
||||
[currentTrack, queue, isPlaying, position, duration, play, toggle, next, prev, seek],
|
||||
);
|
||||
|
||||
return <PlayerContext.Provider value={value}>{children}</PlayerContext.Provider>;
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// Provenance: handielson/Mercado-do-vale-news (fixed).
|
||||
// repo: handielson/Mercado-do-vale-news
|
||||
// commit: 9b5fcf2dae41e56f5f97952266f2d6ba59598598
|
||||
// parent: 70ca282b819ac1d60f4b5e665d224b1043ff1ccc
|
||||
// commit_url: https://github.com/handielson/Mercado-do-vale-news/commit/9b5fcf2dae41e56f5f97952266f2d6ba59598598
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: fetchMetadata
|
||||
// relpath: services/catalogMetadataService.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
async function fetchMetadata(): Promise<MetadataCache | null> {
|
||||
// Deduplicação de requisições concorrentes
|
||||
if (pendingFetch) return pendingFetch;
|
||||
|
||||
pendingFetch = (async () => {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), 10000);
|
||||
|
||||
// Bypass completo de cache de CDN e Browser
|
||||
const timestamp = Date.now();
|
||||
const res = await fetch(buildVpsUrl(`/catalog/metadata?_t=${timestamp}`), {
|
||||
signal: controller.signal,
|
||||
headers: { Accept: 'application/json' },
|
||||
cache: 'no-store',
|
||||
});
|
||||
clearTimeout(timer);
|
||||
if (!res.ok) return null;
|
||||
const data = await res.json();
|
||||
return {
|
||||
categories: data.categories || [],
|
||||
brands: data.brands || [],
|
||||
priceRange: data.priceRange || null,
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
} finally {
|
||||
pendingFetch = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return pendingFetch;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Provenance: handielson/Mercado-do-vale-news (vuln).
|
||||
// repo: handielson/Mercado-do-vale-news
|
||||
// commit: 70ca282b819ac1d60f4b5e665d224b1043ff1ccc
|
||||
// parent: 70ca282b819ac1d60f4b5e665d224b1043ff1ccc
|
||||
// commit_url: https://github.com/handielson/Mercado-do-vale-news/commit/9b5fcf2dae41e56f5f97952266f2d6ba59598598
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: fetchMetadata
|
||||
// relpath: services/catalogMetadataService.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
async function fetchMetadata(): Promise<MetadataCache | null> {
|
||||
// Deduplicação de requisições concorrentes
|
||||
if (pendingFetch) return pendingFetch;
|
||||
|
||||
pendingFetch = (async () => {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), 10000);
|
||||
|
||||
// Bypass completo de cache de CDN e Browser
|
||||
const timestamp = Date.now();
|
||||
const res = await fetch(buildVpsUrl(`/catalog/metadata?_t=${timestamp}`), {
|
||||
signal: controller.signal,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
||||
'Pragma': 'no-cache'
|
||||
},
|
||||
cache: 'no-store',
|
||||
});
|
||||
clearTimeout(timer);
|
||||
if (!res.ok) return null;
|
||||
const data = await res.json();
|
||||
return {
|
||||
categories: data.categories || [],
|
||||
brands: data.brands || [],
|
||||
priceRange: data.priceRange || null,
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
} finally {
|
||||
pendingFetch = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return pendingFetch;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Provenance: andrebubniak/money-track (fixed).
|
||||
// repo: andrebubniak/money-track
|
||||
// commit: 4d4a5b063278c8b6697c3faae133d7c39fcd01c0
|
||||
// parent: add96df6d6a6b61506635c23dbacf6c6cfe24dc2
|
||||
// commit_url: https://github.com/andrebubniak/money-track/commit/4d4a5b063278c8b6697c3faae133d7c39fcd01c0
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: isCategoryIcon
|
||||
// relpath: src/lib/category-icons.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
export function isCategoryIcon(value: string): value is keyof typeof CATEGORY_ICONS {
|
||||
return Object.hasOwn(CATEGORY_ICONS, value);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Provenance: andrebubniak/money-track (vuln).
|
||||
// repo: andrebubniak/money-track
|
||||
// commit: add96df6d6a6b61506635c23dbacf6c6cfe24dc2
|
||||
// parent: add96df6d6a6b61506635c23dbacf6c6cfe24dc2
|
||||
// commit_url: https://github.com/andrebubniak/money-track/commit/4d4a5b063278c8b6697c3faae133d7c39fcd01c0
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: isCategoryIcon
|
||||
// relpath: src/lib/category-icons.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
export function isCategoryIcon(value: string): value is keyof typeof CATEGORY_ICONS {
|
||||
return value in CATEGORY_ICONS;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Provenance: DavideCarvalho/nestjs-filter (fixed).
|
||||
// repo: DavideCarvalho/nestjs-filter
|
||||
// commit: aa0e600d05997ea3d77538ea1c2db427c439f2e8
|
||||
// parent: d899b40d3466f2ffbe9f01c4d49267412401f078
|
||||
// commit_url: https://github.com/DavideCarvalho/nestjs-filter/commit/aa0e600d05997ea3d77538ea1c2db427c439f2e8
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: normalizeInput
|
||||
// relpath: packages/core/src/input/normalizer.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
export function normalizeInput(input: unknown, options: NormalizeOptions): Record<string, unknown> {
|
||||
if (input == null || typeof input !== 'object') return {};
|
||||
const norm = pickNormalizer(options.normalizer);
|
||||
const drop = options.dropId === true;
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const [rawKey, value] of Object.entries(input as Record<string, unknown>)) {
|
||||
if (BLOCKED_KEYS.has(rawKey)) continue;
|
||||
let key = norm(rawKey);
|
||||
if (BLOCKED_KEYS.has(key)) continue;
|
||||
if (drop) key = stripId(key);
|
||||
if (key.length === 0) continue;
|
||||
out[key] = value;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Provenance: DavideCarvalho/nestjs-filter (vuln).
|
||||
// repo: DavideCarvalho/nestjs-filter
|
||||
// commit: d899b40d3466f2ffbe9f01c4d49267412401f078
|
||||
// parent: d899b40d3466f2ffbe9f01c4d49267412401f078
|
||||
// commit_url: https://github.com/DavideCarvalho/nestjs-filter/commit/aa0e600d05997ea3d77538ea1c2db427c439f2e8
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: normalizeInput
|
||||
// relpath: packages/core/src/input/normalizer.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
export function normalizeInput(input: unknown, options: NormalizeOptions): Record<string, unknown> {
|
||||
if (input == null || typeof input !== 'object') return {};
|
||||
const norm = pickNormalizer(options.normalizer);
|
||||
const drop = options.dropId === true;
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const [rawKey, value] of Object.entries(input as Record<string, unknown>)) {
|
||||
let key = norm(rawKey);
|
||||
if (drop) key = stripId(key);
|
||||
if (key.length === 0) continue;
|
||||
out[key] = value;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Provenance: Sachin-Salgar/NEW_ERP_FINAL (fixed).
|
||||
// repo: Sachin-Salgar/NEW_ERP_FINAL
|
||||
// commit: 6e9644c81ce3fb356669157182a5ef09a70c4b59
|
||||
// parent: 08976c5d7a07b0663669b875b4507446199f85d7
|
||||
// commit_url: https://github.com/Sachin-Salgar/NEW_ERP_FINAL/commit/6e9644c81ce3fb356669157182a5ef09a70c4b59
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: origin
|
||||
// relpath: src/presentation/http/app.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export async function createApplication(config: AppConfig, providedPool?: Pool): Promise<FastifyInstance> {
|
||||
const app = Fastify({
|
||||
logger: createLogger(config),
|
||||
requestIdHeader: 'x-request-id',
|
||||
requestIdLogLabel: 'requestId',
|
||||
ignoreTrailingSlash: true,
|
||||
ajv: {
|
||||
customOptions: {
|
||||
allErrors: true,
|
||||
coerceTypes: true,
|
||||
removeAdditional: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const pool = providedPool ?? createDatabasePool(config);
|
||||
const repository = new IdentityAwarePostgresPlatformRepository(pool);
|
||||
const passwordHasher = new BcryptPasswordHasher();
|
||||
const jwtTokenService = new JwtTokenService(config);
|
||||
const authService = new AuthenticationService(repository, passwordHasher, jwtTokenService);
|
||||
const authorizationService = new AuthorizationService(repository);
|
||||
const branchService = new BranchService(repository);
|
||||
const coreEnterpriseService = new CoreEnterpriseService(repository);
|
||||
const locationService = new LocationService(repository);
|
||||
const moduleAccessService = new ModuleAccessService(pool);
|
||||
const registrationService = new UserRegistrationService(repository, passwordHasher);
|
||||
const tenantMembershipService = new TenantMembershipService(repository);
|
||||
|
||||
app.decorate('appConfig', config);
|
||||
app.decorate('authService', authService);
|
||||
app.decorate('authorizationService', authorizationService);
|
||||
app.decorate('branchService', branchService);
|
||||
app.decorate('coreEnterpriseService', coreEnterpriseService);
|
||||
app.decorate('locationService', locationService);
|
||||
app.decorate('moduleAccessService', moduleAccessService);
|
||||
app.decorate('registrationService', registrationService);
|
||||
app.decorate('jwtTokenService', jwtTokenService);
|
||||
app.decorate('tenantMembershipService', tenantMembershipService);
|
||||
|
||||
await app.register(cors, {
|
||||
origin: (origin, callback) => {
|
||||
callback(null, isCorsOriginAllowed(config, origin));
|
||||
},
|
||||
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-tenant-id'],
|
||||
credentials: true,
|
||||
optionsSuccessStatus: 204,
|
||||
});
|
||||
|
||||
app.setErrorHandler(buildErrorHandler(config));
|
||||
|
||||
await app.register(healthRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(authRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(rbacRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(branchRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(coreEnterpriseRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(locationRoutes, { prefix: config.API_PREFIX });
|
||||
|
||||
return app;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Provenance: Sachin-Salgar/NEW_ERP_FINAL (vuln).
|
||||
// repo: Sachin-Salgar/NEW_ERP_FINAL
|
||||
// commit: 08976c5d7a07b0663669b875b4507446199f85d7
|
||||
// parent: 08976c5d7a07b0663669b875b4507446199f85d7
|
||||
// commit_url: https://github.com/Sachin-Salgar/NEW_ERP_FINAL/commit/6e9644c81ce3fb356669157182a5ef09a70c4b59
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: origin
|
||||
// relpath: src/presentation/http/app.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export async function createApplication(config: AppConfig, providedPool?: Pool): Promise<FastifyInstance> {
|
||||
const app = Fastify({
|
||||
logger: createLogger(config),
|
||||
requestIdHeader: 'x-request-id',
|
||||
requestIdLogLabel: 'requestId',
|
||||
ignoreTrailingSlash: true,
|
||||
ajv: {
|
||||
customOptions: {
|
||||
allErrors: true,
|
||||
coerceTypes: true,
|
||||
removeAdditional: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const pool = providedPool ?? createDatabasePool(config);
|
||||
const repository = new IdentityAwarePostgresPlatformRepository(pool);
|
||||
const passwordHasher = new BcryptPasswordHasher();
|
||||
const jwtTokenService = new JwtTokenService(config);
|
||||
const authService = new AuthenticationService(repository, passwordHasher, jwtTokenService);
|
||||
const authorizationService = new AuthorizationService(repository);
|
||||
const branchService = new BranchService(repository);
|
||||
const coreEnterpriseService = new CoreEnterpriseService(repository);
|
||||
const locationService = new LocationService(repository);
|
||||
const moduleAccessService = new ModuleAccessService(pool);
|
||||
const registrationService = new UserRegistrationService(repository, passwordHasher);
|
||||
const tenantMembershipService = new TenantMembershipService(repository);
|
||||
|
||||
app.decorate('appConfig', config);
|
||||
app.decorate('authService', authService);
|
||||
app.decorate('authorizationService', authorizationService);
|
||||
app.decorate('branchService', branchService);
|
||||
app.decorate('coreEnterpriseService', coreEnterpriseService);
|
||||
app.decorate('locationService', locationService);
|
||||
app.decorate('moduleAccessService', moduleAccessService);
|
||||
app.decorate('registrationService', registrationService);
|
||||
app.decorate('jwtTokenService', jwtTokenService);
|
||||
app.decorate('tenantMembershipService', tenantMembershipService);
|
||||
|
||||
await app.register(cors, {
|
||||
origin: (origin, callback) => {
|
||||
callback(null, isCorsOriginAllowed(config, origin));
|
||||
},
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-tenant-id'],
|
||||
credentials: true,
|
||||
optionsSuccessStatus: 204,
|
||||
});
|
||||
|
||||
app.setErrorHandler(buildErrorHandler(config));
|
||||
|
||||
await app.register(healthRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(authRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(rbacRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(branchRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(coreEnterpriseRoutes, { prefix: config.API_PREFIX });
|
||||
await app.register(locationRoutes, { prefix: config.API_PREFIX });
|
||||
|
||||
return app;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// Provenance: Irnhakim/nimestream (fixed).
|
||||
// repo: Irnhakim/nimestream
|
||||
// commit: d17f535bf3012041b056ff3aa991ff6cfa198e43
|
||||
// parent: 0c37bfd9e5292b15b1d7af51f52793d9bdf1cef0
|
||||
// commit_url: https://github.com/Irnhakim/nimestream/commit/d17f535bf3012041b056ff3aa991ff6cfa198e43
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: GET
|
||||
// relpath: app/api/img/route.js
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
export async function GET(request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const imageUrl = searchParams.get('url');
|
||||
|
||||
if (!imageUrl) {
|
||||
return new Response('Missing url parameter', { status: 400 });
|
||||
}
|
||||
|
||||
// Only allow proxying images from allowed domains for security
|
||||
const allowed = [
|
||||
'otakudesu.blog', 'otakudesu.cloud', 'otakudesu.ltd',
|
||||
'i3.wp.com', 'i2.wp.com', 'i1.wp.com', 'i0.wp.com',
|
||||
'cdn.otakudesu', 'kusonime.com', 'wp-content',
|
||||
'oploverz.ac', 'oploverz.site', 'backapi.oploverz', 'alqanime.net',
|
||||
'anichin.cafe', 'samehadaku', 'animasu', 'zoronime', 'anoboy', 'nimegami', 'animeindo', 'animekuindo', 'winbu', 'kuramanime', 'animekompi', 'donghub', 'dramabox'
|
||||
];
|
||||
|
||||
let parsedUrl;
|
||||
try {
|
||||
parsedUrl = new URL(imageUrl);
|
||||
} catch (e) {
|
||||
return new Response('Invalid URL', { status: 400 });
|
||||
}
|
||||
|
||||
const hostname = parsedUrl.hostname;
|
||||
const isAllowed = allowed.some(domain =>
|
||||
hostname === domain || hostname.endsWith(`.${domain}`)
|
||||
);
|
||||
if (!isAllowed) {
|
||||
return new Response('Forbidden', { status: 403 });
|
||||
}
|
||||
|
||||
// Determine proper referer
|
||||
let referer = `${BASE_URL}/`;
|
||||
if (imageUrl.includes('kusonime.com')) {
|
||||
referer = 'https://kusonime.com/';
|
||||
} else if (imageUrl.includes('oploverz.ac') || imageUrl.includes('oploverz.site')) {
|
||||
referer = 'https://oploverz.site/';
|
||||
} else if (imageUrl.includes('alqanime.net')) {
|
||||
referer = 'https://alqanime.net/';
|
||||
} else if (imageUrl.includes('anichin.cafe')) {
|
||||
referer = 'https://anichin.cafe/';
|
||||
} else if (imageUrl.includes('samehadaku')) {
|
||||
referer = 'https://samehadaku.vip/';
|
||||
} else if (imageUrl.includes('animasu')) {
|
||||
referer = 'https://animasu.cc/';
|
||||
} else if (imageUrl.includes('kuramanime')) {
|
||||
referer = 'https://kuramanime.net/';
|
||||
}
|
||||
|
||||
try {
|
||||
// Add abort controller to prevent long timeout waits
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 4000); // 4 seconds timeout limit
|
||||
|
||||
const response = await fetch(imageUrl, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'Referer': referer,
|
||||
'Accept': 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
},
|
||||
signal: controller.signal,
|
||||
cache: 'no-store',
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response.ok) {
|
||||
return new Response('Failed to fetch source image', { status: response.status });
|
||||
}
|
||||
|
||||
const contentType = response.headers.get('content-type') || 'image/jpeg';
|
||||
const imageBuffer = await response.arrayBuffer();
|
||||
|
||||
return new Response(imageBuffer, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': contentType,
|
||||
'Cache-Control': 'public, max-age=86400, stale-while-revalidate=43200',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Image proxy error:', err.message);
|
||||
return new Response('Error loading image', { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Provenance: Irnhakim/nimestream (vuln).
|
||||
// repo: Irnhakim/nimestream
|
||||
// commit: 0c37bfd9e5292b15b1d7af51f52793d9bdf1cef0
|
||||
// parent: 0c37bfd9e5292b15b1d7af51f52793d9bdf1cef0
|
||||
// commit_url: https://github.com/Irnhakim/nimestream/commit/d17f535bf3012041b056ff3aa991ff6cfa198e43
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: GET
|
||||
// relpath: app/api/img/route.js
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
export async function GET(request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const imageUrl = searchParams.get('url');
|
||||
|
||||
if (!imageUrl) {
|
||||
return new Response('Missing url parameter', { status: 400 });
|
||||
}
|
||||
|
||||
// Only allow proxying images from allowed domains for security
|
||||
const allowed = [
|
||||
'otakudesu.blog', 'otakudesu.cloud', 'otakudesu.ltd',
|
||||
'i3.wp.com', 'i2.wp.com', 'i1.wp.com', 'i0.wp.com',
|
||||
'cdn.otakudesu', 'kusonime.com', 'wp-content',
|
||||
'oploverz.ac', 'oploverz.site', 'backapi.oploverz', 'alqanime.net',
|
||||
'anichin.cafe', 'samehadaku', 'animasu', 'zoronime', 'anoboy', 'nimegami', 'animeindo', 'animekuindo', 'winbu', 'kuramanime', 'animekompi', 'donghub', 'dramabox'
|
||||
];
|
||||
const isAllowed = allowed.some(domain => imageUrl.includes(domain));
|
||||
if (!isAllowed) {
|
||||
return new Response('Forbidden', { status: 403 });
|
||||
}
|
||||
|
||||
// Determine proper referer
|
||||
let referer = `${BASE_URL}/`;
|
||||
if (imageUrl.includes('kusonime.com')) {
|
||||
referer = 'https://kusonime.com/';
|
||||
} else if (imageUrl.includes('oploverz.ac') || imageUrl.includes('oploverz.site')) {
|
||||
referer = 'https://oploverz.site/';
|
||||
} else if (imageUrl.includes('alqanime.net')) {
|
||||
referer = 'https://alqanime.net/';
|
||||
} else if (imageUrl.includes('anichin.cafe')) {
|
||||
referer = 'https://anichin.cafe/';
|
||||
} else if (imageUrl.includes('samehadaku')) {
|
||||
referer = 'https://samehadaku.vip/';
|
||||
} else if (imageUrl.includes('animasu')) {
|
||||
referer = 'https://animasu.cc/';
|
||||
} else if (imageUrl.includes('kuramanime')) {
|
||||
referer = 'https://kuramanime.net/';
|
||||
}
|
||||
|
||||
try {
|
||||
// Add abort controller to prevent long timeout waits
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 4000); // 4 seconds timeout limit
|
||||
|
||||
const response = await fetch(imageUrl, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'Referer': referer,
|
||||
'Accept': 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
},
|
||||
signal: controller.signal,
|
||||
cache: 'no-store',
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response.ok) {
|
||||
// Fallback redirect to direct URL if fetch failed but URL is reachable in browser
|
||||
return Response.redirect(imageUrl, 302);
|
||||
}
|
||||
|
||||
const contentType = response.headers.get('content-type') || 'image/jpeg';
|
||||
const imageBuffer = await response.arrayBuffer();
|
||||
|
||||
return new Response(imageBuffer, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': contentType,
|
||||
'Cache-Control': 'public, max-age=86400, stale-while-revalidate=43200',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Image proxy error, falling back to direct redirect:', err.message);
|
||||
return Response.redirect(imageUrl, 302);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# Provenance: HHHHHejia/openniw (fixed).
|
||||
# repo: HHHHHejia/openniw
|
||||
# commit: 0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10
|
||||
# parent: 4d91ed82fa9a5ec6bf5ef96da1d221fc187700dc
|
||||
# commit_url: https://github.com/HHHHHejia/openniw/commit/0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: get_job
|
||||
# relpath: backend/app/routers/jobs.py
|
||||
# provenance: agent
|
||||
# mechanism: identity_from_request_body
|
||||
|
||||
async def get_job(job_id: str, user: dict = Depends(auth.current_user)) -> dict:
|
||||
job = await jobs_service.get(job_id)
|
||||
if job is None:
|
||||
raise HTTPException(404, "Job not found")
|
||||
# Authorization: case-bound jobs are visible only to the case owner;
|
||||
# caseless jobs (free evaluations) are served by the public route only.
|
||||
if job.get("case_id") is None:
|
||||
raise HTTPException(404, "Job not found")
|
||||
await auth.case_owned_by(str(job["case_id"]), user)
|
||||
return {
|
||||
"id": str(job["id"]),
|
||||
"kind": job["kind"],
|
||||
"status": job["status"],
|
||||
"result": job["result"],
|
||||
"error": job["error"],
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# Provenance: HHHHHejia/openniw (vuln).
|
||||
# repo: HHHHHejia/openniw
|
||||
# commit: 4d91ed82fa9a5ec6bf5ef96da1d221fc187700dc
|
||||
# parent: 4d91ed82fa9a5ec6bf5ef96da1d221fc187700dc
|
||||
# commit_url: https://github.com/HHHHHejia/openniw/commit/0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: get_job
|
||||
# relpath: backend/app/routers/jobs.py
|
||||
# provenance: agent
|
||||
# mechanism: identity_from_request_body
|
||||
|
||||
async def get_job(job_id: str, user: dict = Depends(auth.current_user)) -> dict:
|
||||
job = await jobs_service.get(job_id)
|
||||
if job is None:
|
||||
raise HTTPException(404, "Job not found")
|
||||
return {
|
||||
"id": str(job["id"]),
|
||||
"kind": job["kind"],
|
||||
"status": job["status"],
|
||||
"result": job["result"],
|
||||
"error": job["error"],
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# Provenance: ziyuzuo/openniw (fixed).
|
||||
# repo: ziyuzuo/openniw
|
||||
# commit: b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68
|
||||
# parent: 98a0c392ba96cd2c4aa746dd6fc2b183f385225e
|
||||
# commit_url: https://github.com/ziyuzuo/openniw/commit/b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: get_job
|
||||
# relpath: backend/app/routers/jobs.py
|
||||
# provenance: agent
|
||||
# mechanism: identity_from_request_body
|
||||
|
||||
async def get_job(job_id: str, user: dict = Depends(auth.current_user)) -> dict:
|
||||
job = await jobs_service.get(job_id)
|
||||
if job is None:
|
||||
raise HTTPException(404, "Job not found")
|
||||
# Authorization: case-bound jobs are visible only to the case owner;
|
||||
# caseless jobs (free evaluations) are served by the public route only.
|
||||
if job.get("case_id") is None:
|
||||
raise HTTPException(404, "Job not found")
|
||||
await auth.case_owned_by(str(job["case_id"]), user)
|
||||
return {
|
||||
"id": str(job["id"]),
|
||||
"kind": job["kind"],
|
||||
"status": job["status"],
|
||||
"result": job["result"],
|
||||
"error": job["error"],
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# Provenance: ziyuzuo/openniw (vuln).
|
||||
# repo: ziyuzuo/openniw
|
||||
# commit: 98a0c392ba96cd2c4aa746dd6fc2b183f385225e
|
||||
# parent: 98a0c392ba96cd2c4aa746dd6fc2b183f385225e
|
||||
# commit_url: https://github.com/ziyuzuo/openniw/commit/b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: get_job
|
||||
# relpath: backend/app/routers/jobs.py
|
||||
# provenance: agent
|
||||
# mechanism: identity_from_request_body
|
||||
|
||||
async def get_job(job_id: str, user: dict = Depends(auth.current_user)) -> dict:
|
||||
job = await jobs_service.get(job_id)
|
||||
if job is None:
|
||||
raise HTTPException(404, "Job not found")
|
||||
return {
|
||||
"id": str(job["id"]),
|
||||
"kind": job["kind"],
|
||||
"status": job["status"],
|
||||
"result": job["result"],
|
||||
"error": job["error"],
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// Provenance: ZUENS2020/overleaf-with-claude (fixed).
|
||||
// repo: ZUENS2020/overleaf-with-claude
|
||||
// commit: 3980b9e5806defb63e45ae2696e6c1899f3a8431
|
||||
// parent: 5a886aa9fb9fe4e2203f3cb1d62c91f4be0525ed
|
||||
// commit_url: https://github.com/ZUENS2020/overleaf-with-claude/commit/3980b9e5806defb63e45ae2696e6c1899f3a8431
|
||||
// cve:
|
||||
// license: AGPL-3.0
|
||||
// function: exportProject
|
||||
// relpath: services/web/app/src/Features/Exports/ExportsController.mjs
|
||||
// provenance: agent
|
||||
// mechanism: identity_from_request_body
|
||||
|
||||
import { expressify } from '@overleaf/promise-utils'
|
||||
import SessionManager from '../Authentication/SessionManager.mjs'
|
||||
import logger from '@overleaf/logger'
|
||||
import OError from '@overleaf/o-error'
|
||||
import settings from '@overleaf/settings'
|
||||
|
||||
async function exportProject(req, res, next) {
|
||||
const { project_id: projectId, brand_variation_id: brandVariationId } =
|
||||
req.params
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
const exportParams = {
|
||||
project_id: projectId,
|
||||
brand_variation_id: brandVariationId,
|
||||
user_id: userId,
|
||||
}
|
||||
|
||||
if (req.body) {
|
||||
if (req.body.firstName) {
|
||||
exportParams.first_name = req.body.firstName.trim()
|
||||
}
|
||||
if (req.body.lastName) {
|
||||
exportParams.last_name = req.body.lastName.trim()
|
||||
}
|
||||
// additional parameters for gallery exports
|
||||
if (req.body.title) {
|
||||
exportParams.title = req.body.title.trim()
|
||||
}
|
||||
if (req.body.description) {
|
||||
exportParams.description = req.body.description.trim()
|
||||
}
|
||||
if (req.body.author) {
|
||||
exportParams.author = req.body.author.trim()
|
||||
}
|
||||
if (req.body.license) {
|
||||
exportParams.license = req.body.license.trim()
|
||||
}
|
||||
if (req.body.showSource != null) {
|
||||
exportParams.show_source = req.body.showSource
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const exportData = await ExportsHandler.exportProject(exportParams)
|
||||
logger.debug(
|
||||
{
|
||||
userId,
|
||||
projectId,
|
||||
brandVariationId,
|
||||
exportV1Id: exportData.v1_id,
|
||||
},
|
||||
'exported project'
|
||||
)
|
||||
return res.json({
|
||||
export_v1_id: exportData.v1_id,
|
||||
token: exportData.token,
|
||||
message: exportData.message,
|
||||
})
|
||||
} catch (err) {
|
||||
const info = OError.getFullInfo(err)
|
||||
if (info?.forwardResponse) {
|
||||
logger.debug(
|
||||
{ responseError: info.forwardResponse },
|
||||
'forwarding response'
|
||||
)
|
||||
const statusCode = info.forwardResponse.status || 500
|
||||
return res.status(statusCode).json(info.forwardResponse)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Provenance: ZUENS2020/overleaf-with-claude (vuln).
|
||||
// repo: ZUENS2020/overleaf-with-claude
|
||||
// commit: 5a886aa9fb9fe4e2203f3cb1d62c91f4be0525ed
|
||||
// parent: 5a886aa9fb9fe4e2203f3cb1d62c91f4be0525ed
|
||||
// commit_url: https://github.com/ZUENS2020/overleaf-with-claude/commit/3980b9e5806defb63e45ae2696e6c1899f3a8431
|
||||
// cve:
|
||||
// license: AGPL-3.0
|
||||
// function: exportProject
|
||||
// relpath: services/web/app/src/Features/Exports/ExportsController.mjs
|
||||
// provenance: agent
|
||||
// mechanism: identity_from_request_body
|
||||
|
||||
import { expressify } from '@overleaf/promise-utils'
|
||||
import SessionManager from '../Authentication/SessionManager.mjs'
|
||||
import logger from '@overleaf/logger'
|
||||
import OError from '@overleaf/o-error'
|
||||
|
||||
async function exportProject(req, res, next) {
|
||||
const { project_id: projectId, brand_variation_id: brandVariationId } =
|
||||
req.params
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
const exportParams = {
|
||||
project_id: projectId,
|
||||
brand_variation_id: brandVariationId,
|
||||
user_id: userId,
|
||||
}
|
||||
|
||||
if (req.body) {
|
||||
if (req.body.firstName) {
|
||||
exportParams.first_name = req.body.firstName.trim()
|
||||
}
|
||||
if (req.body.lastName) {
|
||||
exportParams.last_name = req.body.lastName.trim()
|
||||
}
|
||||
// additional parameters for gallery exports
|
||||
if (req.body.title) {
|
||||
exportParams.title = req.body.title.trim()
|
||||
}
|
||||
if (req.body.description) {
|
||||
exportParams.description = req.body.description.trim()
|
||||
}
|
||||
if (req.body.author) {
|
||||
exportParams.author = req.body.author.trim()
|
||||
}
|
||||
if (req.body.license) {
|
||||
exportParams.license = req.body.license.trim()
|
||||
}
|
||||
if (req.body.showSource != null) {
|
||||
exportParams.show_source = req.body.showSource
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const exportData = await ExportsHandler.exportProject(exportParams)
|
||||
logger.debug(
|
||||
{
|
||||
userId,
|
||||
projectId,
|
||||
brandVariationId,
|
||||
exportV1Id: exportData.v1_id,
|
||||
},
|
||||
'exported project'
|
||||
)
|
||||
return res.json({
|
||||
export_v1_id: exportData.v1_id,
|
||||
message: exportData.message,
|
||||
})
|
||||
} catch (err) {
|
||||
const info = OError.getFullInfo(err)
|
||||
if (info?.forwardResponse) {
|
||||
logger.debug(
|
||||
{ responseError: info.forwardResponse },
|
||||
'forwarding response'
|
||||
)
|
||||
const statusCode = info.forwardResponse.status || 500
|
||||
return res.status(statusCode).json(info.forwardResponse)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Provenance: dayflower/popmark (fixed).
|
||||
// repo: dayflower/popmark
|
||||
// commit: e5ac407cef37c37178d440541ede301c838640fb
|
||||
// parent: 31d1ac79b4cfa3118597348e79800a6561115149
|
||||
// commit_url: https://github.com/dayflower/popmark/commit/e5ac407cef37c37178d440541ede301c838640fb
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: deepMergeInto
|
||||
// relpath: src/lexical-markdown/config/editorConfig.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function deepMergeInto(
|
||||
target: Record<string, unknown>,
|
||||
source: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
for (const key of Object.keys(source)) {
|
||||
// popmark patch: guard against prototype pollution (CodeQL).
|
||||
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
||||
continue;
|
||||
}
|
||||
const sourceValue = source[key];
|
||||
if (sourceValue === undefined) continue;
|
||||
if (isPlainObject(sourceValue)) {
|
||||
const targetValue = target[key];
|
||||
const nested = isPlainObject(targetValue) ? targetValue : {};
|
||||
target[key] = deepMergeInto(nested, sourceValue);
|
||||
} else {
|
||||
target[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Provenance: dayflower/popmark (vuln).
|
||||
// repo: dayflower/popmark
|
||||
// commit: 31d1ac79b4cfa3118597348e79800a6561115149
|
||||
// parent: 31d1ac79b4cfa3118597348e79800a6561115149
|
||||
// commit_url: https://github.com/dayflower/popmark/commit/e5ac407cef37c37178d440541ede301c838640fb
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: deepMergeInto
|
||||
// relpath: src/lexical-markdown/config/editorConfig.ts
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
function deepMergeInto(
|
||||
target: Record<string, unknown>,
|
||||
source: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
for (const key of Object.keys(source)) {
|
||||
const sourceValue = source[key];
|
||||
if (sourceValue === undefined) continue;
|
||||
if (isPlainObject(sourceValue)) {
|
||||
const targetValue = target[key];
|
||||
const nested = isPlainObject(targetValue) ? targetValue : {};
|
||||
target[key] = deepMergeInto(nested, sourceValue);
|
||||
} else {
|
||||
target[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Provenance: DevilsDev/rag-pipeline-utils (fixed).
|
||||
// repo: DevilsDev/rag-pipeline-utils
|
||||
// commit: 76e5f0a94d6803d0e463d26a61cedb7da90857a7
|
||||
// parent: ba587867118f703632ff2dc63c4feb8ad6793420
|
||||
// commit_url: https://github.com/DevilsDev/rag-pipeline-utils/commit/76e5f0a94d6803d0e463d26a61cedb7da90857a7
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: handleConfigSet
|
||||
// relpath: src/cli/handlers/config-handler.js
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
async function handleConfigSet(globalOptions, key, value) {
|
||||
try {
|
||||
const config = JSON.parse(await fs.readFile(globalOptions.config, "utf-8"));
|
||||
|
||||
// Set value using dot notation
|
||||
const keys = key.split(".");
|
||||
const forbidden = new Set(["__proto__", "constructor", "prototype"]);
|
||||
if (keys.some((k) => forbidden.has(k))) {
|
||||
logger.error("Invalid configuration key: contains restricted property");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let current = config;
|
||||
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
if (!current[keys[i]]) {
|
||||
current[keys[i]] = {};
|
||||
}
|
||||
current = current[keys[i]];
|
||||
}
|
||||
|
||||
// Parse value
|
||||
let parsedValue;
|
||||
try {
|
||||
parsedValue = JSON.parse(value);
|
||||
} catch (error) {
|
||||
parsedValue = value; // Keep as string
|
||||
}
|
||||
|
||||
current[keys[keys.length - 1]] = parsedValue;
|
||||
|
||||
// Save configuration
|
||||
await fs.writeFile(globalOptions.config, JSON.stringify(config, null, 2));
|
||||
console.log("✅ Configuration updated");
|
||||
} catch (error) {
|
||||
logger.error("❌ Failed to set configuration:", error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Provenance: DevilsDev/rag-pipeline-utils (vuln).
|
||||
// repo: DevilsDev/rag-pipeline-utils
|
||||
// commit: ba587867118f703632ff2dc63c4feb8ad6793420
|
||||
// parent: ba587867118f703632ff2dc63c4feb8ad6793420
|
||||
// commit_url: https://github.com/DevilsDev/rag-pipeline-utils/commit/76e5f0a94d6803d0e463d26a61cedb7da90857a7
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: handleConfigSet
|
||||
// relpath: src/cli/handlers/config-handler.js
|
||||
// provenance: agent
|
||||
// mechanism: prototype_pollution
|
||||
|
||||
async function handleConfigSet(globalOptions, key, value) {
|
||||
try {
|
||||
const config = JSON.parse(await fs.readFile(globalOptions.config, "utf-8"));
|
||||
|
||||
// Set value using dot notation
|
||||
const keys = key.split(".");
|
||||
let current = config;
|
||||
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
if (!current[keys[i]]) {
|
||||
current[keys[i]] = {};
|
||||
}
|
||||
current = current[keys[i]];
|
||||
}
|
||||
|
||||
// Parse value
|
||||
let parsedValue;
|
||||
try {
|
||||
parsedValue = JSON.parse(value);
|
||||
} catch (error) {
|
||||
parsedValue = value; // Keep as string
|
||||
}
|
||||
|
||||
current[keys[keys.length - 1]] = parsedValue;
|
||||
|
||||
// Save configuration
|
||||
await fs.writeFile(globalOptions.config, JSON.stringify(config, null, 2));
|
||||
console.log("✅ Configuration updated");
|
||||
} catch (error) {
|
||||
logger.error("❌ Failed to set configuration:", error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,977 @@
|
||||
# agent-vfc candidate recipes from agent-trailer security-fix commits (build_recipes.py).
|
||||
# reviewer = "pending" means a human has not yet confirmed the vulnerability and mechanism.
|
||||
|
||||
[[recipe]]
|
||||
name = "academic-based-qoder-app-a79ddb"
|
||||
host = "github"
|
||||
repo = "1173591564/academic-based-qoder"
|
||||
parent = "8170f0377fe64d1ec2e35769d4ce3d0634d97cef"
|
||||
commit = "a79ddb90def54e91f7507cbf6b1548b224d642aa"
|
||||
path = "services/proxy-hub/backend/proxy_hub/app.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "services/proxy-hub/backend/proxy_hub/app.py"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "academic-based-qoder"
|
||||
trailer = "Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(hub): allow DSH token validation CORS"
|
||||
commit_url = "https://github.com/1173591564/academic-based-qoder/commit/a79ddb90def54e91f7507cbf6b1548b224d642aa"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "anastasios-pw-session-14ec1a"
|
||||
host = "github"
|
||||
repo = "Anas329796/Anastasios"
|
||||
parent = "adb7b0d5d6b81c46d56451c709e7eac9d0dc93fb"
|
||||
commit = "14ec1ac50f9e4e255d875236d30129c6207401d4"
|
||||
path = "extensions/browser/src/browser/pw-session.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "extensions/browser/src/browser/pw-session.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "Anastasios"
|
||||
trailer = "Co-authored-by: Devin Robison <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(browser): harden SSRF redirect guard against non-navigation document hops [AI] (#62355)"
|
||||
commit_url = "https://github.com/Anas329796/Anastasios/commit/14ec1ac50f9e4e255d875236d30129c6207401d4"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "arsnova-eu-httpcors-9bcba4"
|
||||
host = "github"
|
||||
repo = "kqc-real/arsnova.eu"
|
||||
parent = "2ae60c434f3fb80f91807a2ec485ee1a7ec76bd2"
|
||||
commit = "9bcba4f442aecc6a5e16ef2dc6115177cfc2b6df"
|
||||
path = "apps/backend/src/lib/httpCors.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "apps/backend/src/lib/httpCors.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "arsnova.eu"
|
||||
trailer = "Co-authored-by: Cursor <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(security): Produktions-CORS auf Same-Origin begrenzen (#143)"
|
||||
commit_url = "https://github.com/kqc-real/arsnova.eu/commit/9bcba4f442aecc6a5e16ef2dc6115177cfc2b6df"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "astroclaw-pw-session-1553a8"
|
||||
host = "github"
|
||||
repo = "P1R4N351/astroclaw"
|
||||
parent = "d3eed2dc01328f21dd404477bb28e2740fa371a4"
|
||||
commit = "1553a8adf123913cf7f1f1c75be4c4e5cd6c796b"
|
||||
path = "extensions/browser/src/browser/pw-session.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "extensions/browser/src/browser/pw-session.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "astroclaw"
|
||||
trailer = "Co-authored-by: Devin Robison <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(browser): harden SSRF redirect guard against non-navigation document hops [AI] (#62355)"
|
||||
commit_url = "https://github.com/P1R4N351/astroclaw/commit/1553a8adf123913cf7f1f1c75be4c4e5cd6c796b"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "capgo-app-apptabs-7d73fd"
|
||||
host = "github"
|
||||
repo = "Cap-go/capgo.app"
|
||||
parent = "415ea4e19d7da19a3f8b0cd0bba541d60b902522"
|
||||
commit = "7d73fd21a59eaa3a4e20c6dc0d280e73e47435b7"
|
||||
path = "src/constants/appTabs.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "src/constants/appTabs.ts"
|
||||
license = "AGPL-3.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "capgo.app"
|
||||
trailer = "Co-authored-by: Cursor <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(notifications): harden API CORS and mark console tab as beta (#2623)"
|
||||
commit_url = "https://github.com/Cap-go/capgo.app/commit/7d73fd21a59eaa3a4e20c6dc0d280e73e47435b7"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "capgo-app-hono-4dadd2"
|
||||
host = "github"
|
||||
repo = "Cap-go/capgo.app"
|
||||
parent = "8c0ac7e233946abd8dc26581b871e9fcd0928899"
|
||||
commit = "4dadd2580d02213d227a331eee0232aa59859b59"
|
||||
path = "supabase/functions/_backend/utils/hono.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "supabase/functions/_backend/utils/hono.ts"
|
||||
license = "AGPL-3.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "capgo.app"
|
||||
trailer = "Co-authored-by: Cursor <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(api): CORS for Capacitor localhost WebView (#3105)"
|
||||
commit_url = "https://github.com/Cap-go/capgo.app/commit/4dadd2580d02213d227a331eee0232aa59859b59"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "dailyforge-server-ed1470"
|
||||
host = "github"
|
||||
repo = "Annamdevula-Nissi-Grace/Dailyforge"
|
||||
parent = "adc164d6e87ff735a3ea5637a2febfd3217e168a"
|
||||
commit = "ed1470814a108bd725c8b27bd9d86cf95a979a96"
|
||||
path = "backend/src/server.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "backend/src/server.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "Dailyforge"
|
||||
trailer = "Co-authored-by: Copilot <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix: add localhost fallback for CORS origin (#172)"
|
||||
commit_url = "https://github.com/Annamdevula-Nissi-Grace/Dailyforge/commit/ed1470814a108bd725c8b27bd9d86cf95a979a96"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "dnf-plugin-anyrepo-config-26d19a"
|
||||
host = "github"
|
||||
repo = "jfut/dnf-plugin-anyrepo"
|
||||
parent = "33cde479d0db8f45dd89fbdcfb2bc0f1be66bd7a"
|
||||
commit = "26d19aeb8884f244e34ccfdc4f49f07055adc4d0"
|
||||
path = "dnf_plugin_anyrepo/config.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "dnf_plugin_anyrepo/config.py"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "dnf-plugin-anyrepo"
|
||||
trailer = "Co-authored-by: Codex <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(config): prevent path traversal in repository names"
|
||||
commit_url = "https://github.com/jfut/dnf-plugin-anyrepo/commit/26d19aeb8884f244e34ccfdc4f49f07055adc4d0"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "edutrace-page-ee7ba2"
|
||||
host = "github"
|
||||
repo = "jardimdesoftware/edutrace"
|
||||
parent = "c4dc6ddcc5492c77c8a5ad7369c87dea29c001fd"
|
||||
commit = "ee7ba25fb23ea89cc1b67549cb5e32c8ead92739"
|
||||
path = "front/src/app/editar-anamnese/page.tsx"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "front/src/app/editar-anamnese/page.tsx"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
mechanism = "prototype_pollution"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "edutrace"
|
||||
trailer = "Co-Authored-By: Claude Fable 5 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(front): impedir prototype pollution nos handlers de formulário aninhado"
|
||||
commit_url = "https://github.com/jardimdesoftware/edutrace/commit/ee7ba25fb23ea89cc1b67549cb5e32c8ead92739"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "etoj-index-605274"
|
||||
host = "github"
|
||||
repo = "Eternity-Sky/_ETOJ"
|
||||
parent = "b0c020fd9ca0204630fca8a857d6fc1b1497bd5b"
|
||||
commit = "6052743d477eeff62e32553c2790785d3f52c641"
|
||||
path = "api/src/index.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "api/src/index.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "_ETOJ"
|
||||
trailer = "Generated with [Devin](https://devin.ai)"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix CORS: Add PATCH method to allowed methods"
|
||||
commit_url = "https://github.com/Eternity-Sky/_ETOJ/commit/6052743d477eeff62e32553c2790785d3f52c641"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "etude-lexical-markdown-editorconfig-c61a8b"
|
||||
host = "github"
|
||||
repo = "dayflower/etude-lexical-markdown"
|
||||
parent = "0a2184f59e79a04b1365cd49200026e8f2ffdbd5"
|
||||
commit = "c61a8bf78fe20d6ae0eab2e4b8b02004508525ed"
|
||||
path = "src/config/editorConfig.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "src/config/editorConfig.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
mechanism = "prototype_pollution"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "etude-lexical-markdown"
|
||||
trailer = "Co-Authored-By: Claude <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix: guard deepMergeInto against prototype pollution"
|
||||
commit_url = "https://github.com/dayflower/etude-lexical-markdown/commit/c61a8bf78fe20d6ae0eab2e4b8b02004508525ed"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "etude-lexical-markdown-editorconfig-db4f54"
|
||||
host = "github"
|
||||
repo = "dayflower/etude-lexical-markdown"
|
||||
parent = "1c865815d05b072f4973388c3ac66b6696d9efde"
|
||||
commit = "db4f54b1ab80ad596de6425e84f90aa781c49999"
|
||||
path = "src/config/editorConfig.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "src/config/editorConfig.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
mechanism = "prototype_pollution"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "etude-lexical-markdown"
|
||||
trailer = "Co-Authored-By: Claude <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix: make prototype pollution guard recognizable by CodeQL"
|
||||
commit_url = "https://github.com/dayflower/etude-lexical-markdown/commit/db4f54b1ab80ad596de6425e84f90aa781c49999"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "gitim-git-cors-proxy-e4c3a4"
|
||||
host = "github"
|
||||
repo = "CiferaTeam/GitIM"
|
||||
parent = "8afa34d45e119164abec0b76ed77a56f442749a8"
|
||||
commit = "e4c3a4794dbe9fbcce679f7df1ecd2b09b40f9d6"
|
||||
path = "products/gitim/frontend/src/lib/git-cors-proxy.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "products/gitim/frontend/src/lib/git-cors-proxy.ts"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "GitIM"
|
||||
trailer = "Co-authored-by: Codex <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(frontend): use gitim cors proxy by default"
|
||||
commit_url = "https://github.com/CiferaTeam/GitIM/commit/e4c3a4794dbe9fbcce679f7df1ecd2b09b40f9d6"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "lensops-kubernetesmanagement-fe4910"
|
||||
host = "github"
|
||||
repo = "amitknigam84/lensops"
|
||||
parent = "9b87ecc3a44a7fe2a5185cca1fe52441647d5748"
|
||||
commit = "fe49109aedfe21dea4d24d4d9f2fa3f1ecfb6c84"
|
||||
path = "components/KubernetesManagement.tsx"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "components/KubernetesManagement.tsx"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-862"
|
||||
class = "missing authorization"
|
||||
mechanism = "missing_auth_guard"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "lensops"
|
||||
trailer = "Co-Authored-By: Claude Sonnet 4.6 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix missing auth header on namespaces API call"
|
||||
commit_url = "https://github.com/amitknigam84/lensops/commit/fe49109aedfe21dea4d24d4d9f2fa3f1ecfb6c84"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "market-cap-route-4f8ae9"
|
||||
host = "github"
|
||||
repo = "navaneethbv/market-cap"
|
||||
parent = "fec6f024ce72c9c47b61cbac6ce7a35cb2280602"
|
||||
commit = "4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6"
|
||||
path = "app/auth/confirm/route.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "app/auth/confirm/route.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-601"
|
||||
class = "open redirect"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "market-cap"
|
||||
trailer = "Co-Authored-By: Claude Fable 5 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix open redirects on the auth next param"
|
||||
commit_url = "https://github.com/navaneethbv/market-cap/commit/4f8ae9be5519ced5a975f1190e3e4bc43f84e4d6"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "melodix-playerprovider-089931"
|
||||
host = "github"
|
||||
repo = "alexshao3/melodix"
|
||||
parent = "c074fc7413338aefcbea3170ef4d3ba486a8a4b7"
|
||||
commit = "089931ef71ea1e5b7586520baf1a5498e2f05b13"
|
||||
path = "apps/miniapp/src/components/PlayerProvider.tsx"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "apps/miniapp/src/components/PlayerProvider.tsx"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "melodix"
|
||||
trailer = "Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>"
|
||||
reviewer = "pending"
|
||||
evidence = "Merge pull request #17 from alexshao3/devin/1777216143-fix-audio-cors"
|
||||
commit_url = "https://github.com/alexshao3/melodix/commit/089931ef71ea1e5b7586520baf1a5498e2f05b13"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "mercado-do-vale-news-catalogmetadataservice-9b5fcf"
|
||||
host = "github"
|
||||
repo = "handielson/Mercado-do-vale-news"
|
||||
parent = "70ca282b819ac1d60f4b5e665d224b1043ff1ccc"
|
||||
commit = "9b5fcf2dae41e56f5f97952266f2d6ba59598598"
|
||||
path = "services/catalogMetadataService.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "services/catalogMetadataService.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "Mercado-do-vale-news"
|
||||
trailer = "Co-Authored-By: Codex <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(catalog): avoid metadata cors preflight"
|
||||
commit_url = "https://github.com/handielson/Mercado-do-vale-news/commit/9b5fcf2dae41e56f5f97952266f2d6ba59598598"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "money-track-category-icons-4d4a5b"
|
||||
host = "github"
|
||||
repo = "andrebubniak/money-track"
|
||||
parent = "add96df6d6a6b61506635c23dbacf6c6cfe24dc2"
|
||||
commit = "4d4a5b063278c8b6697c3faae133d7c39fcd01c0"
|
||||
path = "src/lib/category-icons.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "src/lib/category-icons.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
mechanism = "prototype_pollution"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "money-track"
|
||||
trailer = "Co-Authored-By: Claude Sonnet 5 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(category-icons): use Object.hasOwn to prevent prototype pollution in type guard"
|
||||
commit_url = "https://github.com/andrebubniak/money-track/commit/4d4a5b063278c8b6697c3faae133d7c39fcd01c0"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "nestjs-filter-normalizer-aa0e60"
|
||||
host = "github"
|
||||
repo = "DavideCarvalho/nestjs-filter"
|
||||
parent = "d899b40d3466f2ffbe9f01c4d49267412401f078"
|
||||
commit = "aa0e600d05997ea3d77538ea1c2db427c439f2e8"
|
||||
path = "packages/core/src/input/normalizer.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "packages/core/src/input/normalizer.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
mechanism = "prototype_pollution"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "nestjs-filter"
|
||||
trailer = "Co-Authored-By: Claude Opus 4.7 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(core): add prototype pollution guard to normalizeInput"
|
||||
commit_url = "https://github.com/DavideCarvalho/nestjs-filter/commit/aa0e600d05997ea3d77538ea1c2db427c439f2e8"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "new-erp-final-app-6e9644"
|
||||
host = "github"
|
||||
repo = "Sachin-Salgar/NEW_ERP_FINAL"
|
||||
parent = "08976c5d7a07b0663669b875b4507446199f85d7"
|
||||
commit = "6e9644c81ce3fb356669157182a5ef09a70c4b59"
|
||||
path = "src/presentation/http/app.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "src/presentation/http/app.ts"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "NEW_ERP_FINAL"
|
||||
trailer = "Co-authored-by: Copilot <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix: allow patch requests through cors"
|
||||
commit_url = "https://github.com/Sachin-Salgar/NEW_ERP_FINAL/commit/6e9644c81ce3fb356669157182a5ef09a70c4b59"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "nimestream-route-d17f53"
|
||||
host = "github"
|
||||
repo = "Irnhakim/nimestream"
|
||||
parent = "0c37bfd9e5292b15b1d7af51f52793d9bdf1cef0"
|
||||
commit = "d17f535bf3012041b056ff3aa991ff6cfa198e43"
|
||||
path = "app/api/img/route.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "app/api/img/route.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "nimestream"
|
||||
trailer = "Co-Authored-By: Claude <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix: resolve command injection and SSRF/Open Redirect security issues in multiScraper and image proxy API"
|
||||
commit_url = "https://github.com/Irnhakim/nimestream/commit/d17f535bf3012041b056ff3aa991ff6cfa198e43"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "onlook-helper-57ce1c"
|
||||
host = "github"
|
||||
repo = "zhcndoc/onlook"
|
||||
parent = "cb97e012729eca441e09b1503282cb4bc2f4bcfb"
|
||||
commit = "57ce1ccfacc7e8484cae59013a2b1e34518560e5"
|
||||
path = "apps/web/client/src/server/api/routers/project/helper.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "apps/web/client/src/server/api/routers/project/helper.ts"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2025
|
||||
cwe = "CWE-862"
|
||||
class = "missing authorization"
|
||||
mechanism = "missing_auth_guard"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "onlook"
|
||||
trailer = "Co-Authored-By: Claude <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix CVE-2025-63783: Add authorization checks to project mutation APIs (#3062)"
|
||||
commit_url = "https://github.com/zhcndoc/onlook/commit/57ce1ccfacc7e8484cae59013a2b1e34518560e5"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "openniw-jobs-0fc947"
|
||||
host = "github"
|
||||
repo = "HHHHHejia/openniw"
|
||||
parent = "4d91ed82fa9a5ec6bf5ef96da1d221fc187700dc"
|
||||
commit = "0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10"
|
||||
path = "backend/app/routers/jobs.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "backend/app/routers/jobs.py"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
mechanism = "identity_from_request_body"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "openniw"
|
||||
trailer = "Co-Authored-By: Claude Fable 5 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix IDOR on job endpoint: case-bound jobs require case ownership"
|
||||
commit_url = "https://github.com/HHHHHejia/openniw/commit/0fc94733f6ca3c6b129a0a8e6d7b3acce19d5a10"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "openniw-jobs-b74de3"
|
||||
host = "github"
|
||||
repo = "ziyuzuo/openniw"
|
||||
parent = "98a0c392ba96cd2c4aa746dd6fc2b183f385225e"
|
||||
commit = "b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68"
|
||||
path = "backend/app/routers/jobs.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "backend/app/routers/jobs.py"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
mechanism = "identity_from_request_body"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "openniw"
|
||||
trailer = "Co-Authored-By: Claude Fable 5 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix IDOR on job endpoint: case-bound jobs require case ownership"
|
||||
commit_url = "https://github.com/ziyuzuo/openniw/commit/b74de31b0a5f37e4e929ba6aa74dbe0f5e6d9a68"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "overleaf-with-claude-exportscontroller-3980b9"
|
||||
host = "github"
|
||||
repo = "ZUENS2020/overleaf-with-claude"
|
||||
parent = "5a886aa9fb9fe4e2203f3cb1d62c91f4be0525ed"
|
||||
commit = "3980b9e5806defb63e45ae2696e6c1899f3a8431"
|
||||
path = "services/web/app/src/Features/Exports/ExportsController.mjs"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "services/web/app/src/Features/Exports/ExportsController.mjs"
|
||||
license = "AGPL-3.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
mechanism = "identity_from_request_body"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "overleaf-with-claude"
|
||||
trailer = "Co-authored-by: briangough <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix IDOR in exports by adding token verification (Issue #31637) (#32883)"
|
||||
commit_url = "https://github.com/ZUENS2020/overleaf-with-claude/commit/3980b9e5806defb63e45ae2696e6c1899f3a8431"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "popmark-editorconfig-e5ac40"
|
||||
host = "github"
|
||||
repo = "dayflower/popmark"
|
||||
parent = "31d1ac79b4cfa3118597348e79800a6561115149"
|
||||
commit = "e5ac407cef37c37178d440541ede301c838640fb"
|
||||
path = "src/lexical-markdown/config/editorConfig.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "src/lexical-markdown/config/editorConfig.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
mechanism = "prototype_pollution"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "popmark"
|
||||
trailer = "Co-Authored-By: Claude <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix: guard deepMergeInto against prototype pollution"
|
||||
commit_url = "https://github.com/dayflower/popmark/commit/e5ac407cef37c37178d440541ede301c838640fb"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "rag-pipeline-utils-config-handler-76e5f0"
|
||||
host = "github"
|
||||
repo = "DevilsDev/rag-pipeline-utils"
|
||||
parent = "ba587867118f703632ff2dc63c4feb8ad6793420"
|
||||
commit = "76e5f0a94d6803d0e463d26a61cedb7da90857a7"
|
||||
path = "src/cli/handlers/config-handler.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "src/cli/handlers/config-handler.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-1321"
|
||||
class = "prototype pollution"
|
||||
mechanism = "prototype_pollution"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "rag-pipeline-utils"
|
||||
trailer = "Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(security): prevent prototype pollution in config-handler"
|
||||
commit_url = "https://github.com/DevilsDev/rag-pipeline-utils/commit/76e5f0a94d6803d0e463d26a61cedb7da90857a7"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "registry-proxy-worker-426847"
|
||||
host = "github"
|
||||
repo = "agents-repo/registry-proxy"
|
||||
parent = "6d5937972510cdb5ebca30607b538fdc2e280094"
|
||||
commit = "426847899eb2ee94ae4e5a3aacc50423e36d2dc8"
|
||||
path = "src/worker.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "src/worker.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "registry-proxy"
|
||||
trailer = "Co-authored-by: Cursor <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix: handle CORS OPTIONS preflight for catalog fetches (#10)"
|
||||
commit_url = "https://github.com/agents-repo/registry-proxy/commit/426847899eb2ee94ae4e5a3aacc50423e36d2dc8"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "rls-alembic-rls-d2b6af"
|
||||
host = "github"
|
||||
repo = "DelfinaCare/rls"
|
||||
parent = "670123485f1c657e9faeb18e633339b6a79e696f"
|
||||
commit = "d2b6af47347fb285b7a3820a7f2d5dded20907ec"
|
||||
path = "rls/alembic_rls.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "rls/alembic_rls.py"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "rls"
|
||||
trailer = "Co-authored-by: aebrahim <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Guard against ENABLE ROW LEVEL SECURITY on tables with no policies (#143)"
|
||||
commit_url = "https://github.com/DelfinaCare/rls/commit/d2b6af47347fb285b7a3820a7f2d5dded20907ec"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "supplieradvisor-mvp-route-387bcf"
|
||||
host = "github"
|
||||
repo = "bigfivefoods/supplieradvisor-mvp"
|
||||
parent = "a7a9bc260d649ea2e582c07435bfd7d93100647b"
|
||||
commit = "387bcf40e984a2ee1832ab7beabf0284c5b627d8"
|
||||
path = "app/api/customers/claims/route.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "app/api/customers/claims/route.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
mechanism = "identity_from_request_body"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "supplieradvisor-mvp"
|
||||
trailer = "Co-authored-by: bigfivefoods <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Brief 62: Fix IDOR on customer_claims PATCH/DELETE (#156)"
|
||||
commit_url = "https://github.com/bigfivefoods/supplieradvisor-mvp/commit/387bcf40e984a2ee1832ab7beabf0284c5b627d8"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "supplieradvisor-mvp-route-a69e8f"
|
||||
host = "github"
|
||||
repo = "bigfivefoods/supplieradvisor-mvp"
|
||||
parent = "8558538471e4fb10856f8d9a17d2be5ab5c4fb9c"
|
||||
commit = "a69e8f27c0f4d402573d16f0612b51155bbc46e1"
|
||||
path = "app/api/customers/opportunities/route.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "app/api/customers/opportunities/route.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-639"
|
||||
class = "insecure direct object reference"
|
||||
mechanism = "identity_from_request_body"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "supplieradvisor-mvp"
|
||||
trailer = "Co-authored-by: bigfivefoods <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Brief 60: Fix IDOR on opportunities GET/PATCH/DELETE (missing company membership checks) (#148)"
|
||||
commit_url = "https://github.com/bigfivefoods/supplieradvisor-mvp/commit/a69e8f27c0f4d402573d16f0612b51155bbc46e1"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "tools-cli-tools-a96bc0"
|
||||
host = "github"
|
||||
repo = "D-sorganization/Tools"
|
||||
parent = "e735d28b82dd1fbc42c0ae01157b38d1b4c7c864"
|
||||
commit = "a96bc0502a3dcdac303e4f0152508886e5c35c0a"
|
||||
path = "src/shared/python/ai/tools/cli_tools.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "src/shared/python/ai/tools/cli_tools.py"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "Tools"
|
||||
trailer = "Co-authored-by: dieterolson <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "🛡️ Sentinel: [CRITICAL] Fix command injection in ShellTool (#3307)"
|
||||
commit_url = "https://github.com/D-sorganization/Tools/commit/a96bc0502a3dcdac303e4f0152508886e5c35c0a"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "tools-wsgi-e18686"
|
||||
host = "github"
|
||||
repo = "D-sorganization/Tools"
|
||||
parent = "f34c44a0842ac983e2a984fe7fd985be3ccaf747"
|
||||
commit = "e18686aaa174a8a4843c07b4727771c92e0f179e"
|
||||
path = "src/web_applications/unit_converter/wsgi.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "src/web_applications/unit_converter/wsgi.py"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "Tools"
|
||||
trailer = "Co-Authored-By: Claude Sonnet 4.6 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(security): validate mesh filenames against path traversal in _download_meshes (#2077) (#2107)"
|
||||
commit_url = "https://github.com/D-sorganization/Tools/commit/e18686aaa174a8a4843c07b4727771c92e0f179e"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "trackly-cli-path-diagnostics-1c1aed"
|
||||
host = "github"
|
||||
repo = "trackly-app/trackly-cli"
|
||||
parent = "8d240ad8d7fc114c8f941ad956a2fdf32391ff60"
|
||||
commit = "1c1aed89b07edb04051830c8f086e02b65e961c6"
|
||||
path = "lib/path-diagnostics.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/path-diagnostics.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "trackly-cli"
|
||||
trailer = "Co-authored-by: Codex <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(apply): report blocked path traversal"
|
||||
commit_url = "https://github.com/trackly-app/trackly-cli/commit/1c1aed89b07edb04051830c8f086e02b65e961c6"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "upstreamdrift-local-server-c3a078"
|
||||
host = "github"
|
||||
repo = "D-sorganization/UpstreamDrift"
|
||||
parent = "e28d1da5e103d93951ef11b78a6e9b89ac1fa2bc"
|
||||
commit = "c3a0787080489b30e2ed0abfac03b51e45da184b"
|
||||
path = "src/api/local_server.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "src/api/local_server.py"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "UpstreamDrift"
|
||||
trailer = "Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(api): harden local server path traversal (#2805) (#2839)"
|
||||
commit_url = "https://github.com/D-sorganization/UpstreamDrift/commit/c3a0787080489b30e2ed0abfac03b51e45da184b"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "vantalk-firebase-16c3b0"
|
||||
host = "github"
|
||||
repo = "NiSeullent/VanTalk"
|
||||
parent = "7d442bdf537df96c756d47cfc6ce0ccdb3cd8ea7"
|
||||
commit = "16c3b02875b1f51c3cac1dc185e199978a35985c"
|
||||
path = "web/src/firebase.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "web/src/firebase.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-798"
|
||||
class = "hardcoded credentials"
|
||||
mechanism = "secret_in_client"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "VanTalk"
|
||||
trailer = "Co-authored-by: Cursor <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(security): load Firebase API key from env, remove hardcoded secret"
|
||||
commit_url = "https://github.com/NiSeullent/VanTalk/commit/16c3b02875b1f51c3cac1dc185e199978a35985c"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "waggledance-swarm-ssrf-host-guard-9a4548"
|
||||
host = "github"
|
||||
repo = "Ahkeratmehilaiset/waggledance-swarm"
|
||||
parent = "934b939f1cca5259eaf807db3319eb97b90d8d80"
|
||||
commit = "9a454843aa35332ff2eb3106023eee0c4b5e444b"
|
||||
path = "waggledance/core/v3_13_0/ssrf_host_guard.py"
|
||||
mode = "hunk"
|
||||
language = "python"
|
||||
relpath = "waggledance/core/v3_13_0/ssrf_host_guard.py"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-918"
|
||||
class = "server-side request forgery"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "waggledance-swarm"
|
||||
trailer = "Co-authored-by: codex-lead-1 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(ssrf): reject bare-string allowed hosts (#1460)"
|
||||
commit_url = "https://github.com/Ahkeratmehilaiset/waggledance-swarm/commit/9a454843aa35332ff2eb3106023eee0c4b5e444b"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "workers-research-utils-209444"
|
||||
host = "github"
|
||||
repo = "G4brym/workers-research"
|
||||
parent = "eab923ad3099c01b002fbd6be7cf994614bbdee4"
|
||||
commit = "209444eb61cc564c2d6b43267256f85fe3e5e30e"
|
||||
path = "src/utils.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "src/utils.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-89"
|
||||
class = "sql injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "workers-research"
|
||||
trailer = "Co-Authored-By: Claude Opus 4.6 <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "Fix SQL injection in search by using parameterized queries (#41)"
|
||||
commit_url = "https://github.com/G4brym/workers-research/commit/209444eb61cc564c2d6b43267256f85fe3e5e30e"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "zoonk-origin-bfbf67"
|
||||
host = "github"
|
||||
repo = "zoonk/zoonk"
|
||||
parent = "2604269350bff51f58572c133b45010cb0976a5a"
|
||||
commit = "bfbf670ccb41d63c407d32c51bd26e626a174f31"
|
||||
path = "packages/utils/src/origin.ts"
|
||||
mode = "hunk"
|
||||
language = "typescript"
|
||||
relpath = "packages/utils/src/origin.ts"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2026
|
||||
cwe = "CWE-16"
|
||||
class = "permissive default"
|
||||
mechanism = "permissive_default"
|
||||
provenance = "agent"
|
||||
origin = "github-agent-trailer"
|
||||
project = "zoonk"
|
||||
trailer = "Co-authored-by: Codex <[email protected]>"
|
||||
reviewer = "pending"
|
||||
evidence = "fix(api): allow staging cors from previews (#1559)"
|
||||
commit_url = "https://github.com/zoonk/zoonk/commit/bfbf670ccb41d63c407d32c51bd26e626a174f31"
|
||||
split = "train"
|
||||
@@ -0,0 +1,43 @@
|
||||
// Provenance: agents-repo/registry-proxy (fixed).
|
||||
// repo: agents-repo/registry-proxy
|
||||
// commit: 426847899eb2ee94ae4e5a3aacc50423e36d2dc8
|
||||
// parent: 6d5937972510cdb5ebca30607b538fdc2e280094
|
||||
// commit_url: https://github.com/agents-repo/registry-proxy/commit/426847899eb2ee94ae4e5a3aacc50423e36d2dc8
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: buildUpstreamRequest
|
||||
// relpath: src/worker.js
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
function buildUpstreamRequest(target, env, requestHeaders) {
|
||||
const headers = new Headers();
|
||||
const requestAccept = requestHeaders.get("Accept") || "*/*";
|
||||
headers.set("User-Agent", UPSTREAM_USER_AGENT);
|
||||
|
||||
const ifNoneMatch = requestHeaders.get("If-None-Match");
|
||||
if (ifNoneMatch) {
|
||||
headers.set("If-None-Match", ifNoneMatch);
|
||||
}
|
||||
|
||||
const ifModifiedSince = requestHeaders.get("If-Modified-Since");
|
||||
if (ifModifiedSince) {
|
||||
headers.set("If-Modified-Since", ifModifiedSince);
|
||||
}
|
||||
|
||||
if (env.GITHUB_TOKEN) {
|
||||
headers.set("Accept", "application/vnd.github.raw");
|
||||
headers.set("Authorization", `Bearer ${env.GITHUB_TOKEN}`);
|
||||
return {
|
||||
url: buildContentsApiUrl(target.ref, target.targetPath),
|
||||
headers,
|
||||
};
|
||||
}
|
||||
|
||||
headers.set("Accept", requestAccept);
|
||||
|
||||
return {
|
||||
url: buildUpstreamUrl(target.ref, target.targetPath),
|
||||
headers,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Provenance: agents-repo/registry-proxy (vuln).
|
||||
// repo: agents-repo/registry-proxy
|
||||
// commit: 6d5937972510cdb5ebca30607b538fdc2e280094
|
||||
// parent: 6d5937972510cdb5ebca30607b538fdc2e280094
|
||||
// commit_url: https://github.com/agents-repo/registry-proxy/commit/426847899eb2ee94ae4e5a3aacc50423e36d2dc8
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: buildUpstreamRequest
|
||||
// relpath: src/worker.js
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
function buildUpstreamRequest(target, env, requestHeaders) {
|
||||
const headers = new Headers();
|
||||
const requestAccept = requestHeaders.get("Accept") || "*/*";
|
||||
headers.set("User-Agent", UPSTREAM_USER_AGENT);
|
||||
|
||||
if (env.GITHUB_TOKEN) {
|
||||
headers.set("Accept", "application/vnd.github.raw");
|
||||
headers.set("Authorization", `Bearer ${env.GITHUB_TOKEN}`);
|
||||
return {
|
||||
url: buildContentsApiUrl(target.ref, target.targetPath),
|
||||
headers,
|
||||
};
|
||||
}
|
||||
|
||||
headers.set("Accept", requestAccept);
|
||||
|
||||
return {
|
||||
url: buildUpstreamUrl(target.ref, target.targetPath),
|
||||
headers,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Provenance: bigfivefoods/supplieradvisor-mvp (fixed).
|
||||
// repo: bigfivefoods/supplieradvisor-mvp
|
||||
// commit: 387bcf40e984a2ee1832ab7beabf0284c5b627d8
|
||||
// parent: a7a9bc260d649ea2e582c07435bfd7d93100647b
|
||||
// commit_url: https://github.com/bigfivefoods/supplieradvisor-mvp/commit/387bcf40e984a2ee1832ab7beabf0284c5b627d8
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: PATCH
|
||||
// relpath: app/api/customers/claims/route.ts
|
||||
// provenance: agent
|
||||
// mechanism: identity_from_request_body
|
||||
|
||||
export async function PATCH(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const claimId = Number(body.id);
|
||||
const companyId = Number(body.companyId);
|
||||
if (!Number.isFinite(claimId) || claimId <= 0) {
|
||||
return NextResponse.json({ error: 'id required' }, { status: 400 });
|
||||
}
|
||||
if (!Number.isFinite(companyId) || companyId <= 0) {
|
||||
return NextResponse.json({ error: 'companyId required' }, { status: 400 });
|
||||
}
|
||||
|
||||
const _gate = await requireCompanyAccess(request, companyId, { legacyPrivyUserId: legacyPrivyFrom(request) });
|
||||
if (!_gate.ok) return _gate.response;
|
||||
|
||||
const supabase = getSupabaseServer();
|
||||
const { data: existing, error: fetchError } = await supabase
|
||||
.from('customer_claims')
|
||||
.select('*')
|
||||
.eq('id', claimId)
|
||||
.eq('profile_id', companyId)
|
||||
.single();
|
||||
if (fetchError || !existing) {
|
||||
return NextResponse.json({ error: 'Claim not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
const fields = [
|
||||
'status',
|
||||
'priority',
|
||||
'title',
|
||||
'description',
|
||||
'amount_claimed',
|
||||
'amount_approved',
|
||||
'resolution_notes',
|
||||
'owner_name',
|
||||
'claim_type',
|
||||
] as const;
|
||||
const updates: Record<string, unknown> = { updated_at: new Date().toISOString() };
|
||||
for (const f of fields) {
|
||||
if (body[f] !== undefined) updates[f] = body[f];
|
||||
}
|
||||
if (['resolved', 'closed', 'approved', 'rejected'].includes(String(body.status))) {
|
||||
updates.resolved_at = new Date().toISOString();
|
||||
}
|
||||
const { data, error } = await supabase
|
||||
.from('customer_claims')
|
||||
.update(updates)
|
||||
.eq('id', claimId)
|
||||
.eq('profile_id', companyId)
|
||||
.select('*')
|
||||
.single();
|
||||
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
return NextResponse.json({ success: true, claim: data });
|
||||
} catch (e: unknown) {
|
||||
return NextResponse.json({ error: e instanceof Error ? e.message : 'Error' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Provenance: bigfivefoods/supplieradvisor-mvp (vuln).
|
||||
// repo: bigfivefoods/supplieradvisor-mvp
|
||||
// commit: a7a9bc260d649ea2e582c07435bfd7d93100647b
|
||||
// parent: a7a9bc260d649ea2e582c07435bfd7d93100647b
|
||||
// commit_url: https://github.com/bigfivefoods/supplieradvisor-mvp/commit/387bcf40e984a2ee1832ab7beabf0284c5b627d8
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: PATCH
|
||||
// relpath: app/api/customers/claims/route.ts
|
||||
// provenance: agent
|
||||
// mechanism: identity_from_request_body
|
||||
|
||||
export async function PATCH(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
if (!body.id) return NextResponse.json({ error: 'id required' }, { status: 400 });
|
||||
const fields = [
|
||||
'status',
|
||||
'priority',
|
||||
'title',
|
||||
'description',
|
||||
'amount_claimed',
|
||||
'amount_approved',
|
||||
'resolution_notes',
|
||||
'owner_name',
|
||||
'claim_type',
|
||||
] as const;
|
||||
const updates: Record<string, unknown> = { updated_at: new Date().toISOString() };
|
||||
for (const f of fields) {
|
||||
if (body[f] !== undefined) updates[f] = body[f];
|
||||
}
|
||||
if (['resolved', 'closed', 'approved', 'rejected'].includes(String(body.status))) {
|
||||
updates.resolved_at = new Date().toISOString();
|
||||
}
|
||||
const supabase = getSupabaseServer();
|
||||
const { data, error } = await supabase
|
||||
.from('customer_claims')
|
||||
.update(updates)
|
||||
.eq('id', Number(body.id))
|
||||
.select('*')
|
||||
.single();
|
||||
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
return NextResponse.json({ success: true, claim: data });
|
||||
} catch (e: unknown) {
|
||||
return NextResponse.json({ error: e instanceof Error ? e.message : 'Error' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Provenance: bigfivefoods/supplieradvisor-mvp (fixed).
|
||||
// repo: bigfivefoods/supplieradvisor-mvp
|
||||
// commit: a69e8f27c0f4d402573d16f0612b51155bbc46e1
|
||||
// parent: 8558538471e4fb10856f8d9a17d2be5ab5c4fb9c
|
||||
// commit_url: https://github.com/bigfivefoods/supplieradvisor-mvp/commit/a69e8f27c0f4d402573d16f0612b51155bbc46e1
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: GET
|
||||
// relpath: app/api/customers/opportunities/route.ts
|
||||
// provenance: agent
|
||||
// mechanism: identity_from_request_body
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const companyId = Number(request.nextUrl.searchParams.get('companyId'));
|
||||
const stage = request.nextUrl.searchParams.get('stage');
|
||||
const q = (request.nextUrl.searchParams.get('q') || '').trim().toLowerCase();
|
||||
if (!Number.isFinite(companyId) || companyId <= 0) {
|
||||
return NextResponse.json({ error: 'companyId required' }, { status: 400 });
|
||||
}
|
||||
const _gate = await requireCompanyAccess(request, companyId, { legacyPrivyUserId: legacyPrivyFrom(request) });
|
||||
if (!_gate.ok) return _gate.response;
|
||||
const supabase = getSupabaseServer();
|
||||
const { loadHoldingSubtree, annotateGroupOpportunity } = await import(
|
||||
'@/lib/business/holding-pipeline'
|
||||
);
|
||||
const tree = await loadHoldingSubtree(companyId);
|
||||
let query = supabase
|
||||
.from('opportunities')
|
||||
.select('*')
|
||||
.in('profile_id', tree.ids)
|
||||
.order('updated_at', { ascending: false })
|
||||
.limit(2000);
|
||||
if (stage && stage !== 'all') {
|
||||
query = query.or(`stage.eq.${stage},status.eq.${stage}`);
|
||||
}
|
||||
|
||||
const { data, error } = await query;
|
||||
if (error) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
opportunities: [],
|
||||
warning: error.message,
|
||||
hint: 'Run 20260709_crm_leads_opportunities.sql',
|
||||
});
|
||||
}
|
||||
|
||||
let opportunities: OpportunityListItem[] = (data || []).map((raw) => {
|
||||
const o = raw as Record<string, unknown>;
|
||||
const st = normalizeStage(
|
||||
o.stage as string | null,
|
||||
o.status as string | null
|
||||
);
|
||||
const amount = Number(o.amount ?? o.opportunity_size ?? 0);
|
||||
const probability =
|
||||
o.probability != null ? Number(o.probability) : stageProbability(st);
|
||||
const openDate =
|
||||
toDateOnly(o.open_date as string | null) ||
|
||||
toDateOnly(o.created_at as string | null) ||
|
||||
null;
|
||||
const expectedClose =
|
||||
toDateOnly(o.expected_close_date as string | null) ||
|
||||
toDateOnly(o.estimated_date as string | null) ||
|
||||
null;
|
||||
const actualClose = toDateOnly(o.actual_close_date as string | null);
|
||||
const annotated = annotateGroupOpportunity(
|
||||
{ ...o, stage: st, amount, probability },
|
||||
companyId,
|
||||
tree.names
|
||||
);
|
||||
return {
|
||||
...o,
|
||||
...annotated,
|
||||
name: o.name ?? null,
|
||||
contact_name: o.contact_name ?? null,
|
||||
company_name: o.company_name ?? null,
|
||||
contact_email: o.contact_email ?? null,
|
||||
product_interest: o.product_interest ?? null,
|
||||
stage: st,
|
||||
amount,
|
||||
probability,
|
||||
open_date: openDate,
|
||||
expected_close_date: expectedClose,
|
||||
actual_close_date: actualClose,
|
||||
contact_phone: o.contact_phone || o.contact_number || null,
|
||||
location: o.location || o.opportunity_location || null,
|
||||
description: o.description || o.notes || null,
|
||||
weighted_amount: Math.round((amount * probability) / 100),
|
||||
days_to_expected:
|
||||
openDate && expectedClose
|
||||
? Math.round(
|
||||
(new Date(expectedClose).getTime() -
|
||||
new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: null,
|
||||
days_to_close:
|
||||
openDate && actualClose
|
||||
? Math.round(
|
||||
(new Date(actualClose).getTime() -
|
||||
new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: null,
|
||||
days_open:
|
||||
openDate && !actualClose
|
||||
? Math.round(
|
||||
(Date.now() - new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: openDate && actualClose
|
||||
? Math.round(
|
||||
(new Date(actualClose).getTime() -
|
||||
new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: null,
|
||||
};
|
||||
});
|
||||
|
||||
if (q) {
|
||||
opportunities = opportunities.filter((o) => {
|
||||
const hay = [
|
||||
searchHay(o.name),
|
||||
searchHay(o.contact_name),
|
||||
searchHay(o.company_name),
|
||||
searchHay(o.contact_email),
|
||||
searchHay(o.contact_phone),
|
||||
searchHay(o.stage),
|
||||
searchHay(o.product_interest),
|
||||
]
|
||||
.join(' ')
|
||||
.toLowerCase();
|
||||
return hay.includes(q);
|
||||
});
|
||||
}
|
||||
|
||||
const { summarizeGroupPipeline } = await import(
|
||||
'@/lib/business/group-pipeline-view'
|
||||
);
|
||||
const group = summarizeGroupPipeline({
|
||||
viewerCompanyId: companyId,
|
||||
names: tree.names,
|
||||
companyIds: tree.ids,
|
||||
isSubsidiary: tree.isSubsidiary,
|
||||
opportunities,
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
opportunities,
|
||||
group,
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
return NextResponse.json({ error: e instanceof Error ? e.message : 'Error' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
// Provenance: bigfivefoods/supplieradvisor-mvp (vuln).
|
||||
// repo: bigfivefoods/supplieradvisor-mvp
|
||||
// commit: 8558538471e4fb10856f8d9a17d2be5ab5c4fb9c
|
||||
// parent: 8558538471e4fb10856f8d9a17d2be5ab5c4fb9c
|
||||
// commit_url: https://github.com/bigfivefoods/supplieradvisor-mvp/commit/a69e8f27c0f4d402573d16f0612b51155bbc46e1
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: GET
|
||||
// relpath: app/api/customers/opportunities/route.ts
|
||||
// provenance: agent
|
||||
// mechanism: identity_from_request_body
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const companyId = Number(request.nextUrl.searchParams.get('companyId'));
|
||||
const stage = request.nextUrl.searchParams.get('stage');
|
||||
const q = (request.nextUrl.searchParams.get('q') || '').trim().toLowerCase();
|
||||
if (!Number.isFinite(companyId)) {
|
||||
return NextResponse.json({ error: 'companyId required' }, { status: 400 });
|
||||
}
|
||||
const supabase = getSupabaseServer();
|
||||
const { loadHoldingSubtree, annotateGroupOpportunity } = await import(
|
||||
'@/lib/business/holding-pipeline'
|
||||
);
|
||||
const tree = await loadHoldingSubtree(companyId);
|
||||
let query = supabase
|
||||
.from('opportunities')
|
||||
.select('*')
|
||||
.in('profile_id', tree.ids)
|
||||
.order('updated_at', { ascending: false })
|
||||
.limit(2000);
|
||||
if (stage && stage !== 'all') {
|
||||
query = query.or(`stage.eq.${stage},status.eq.${stage}`);
|
||||
}
|
||||
|
||||
const { data, error } = await query;
|
||||
if (error) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
opportunities: [],
|
||||
warning: error.message,
|
||||
hint: 'Run 20260709_crm_leads_opportunities.sql',
|
||||
});
|
||||
}
|
||||
|
||||
let opportunities: OpportunityListItem[] = (data || []).map((raw) => {
|
||||
const o = raw as Record<string, unknown>;
|
||||
const st = normalizeStage(
|
||||
o.stage as string | null,
|
||||
o.status as string | null
|
||||
);
|
||||
const amount = Number(o.amount ?? o.opportunity_size ?? 0);
|
||||
const probability =
|
||||
o.probability != null ? Number(o.probability) : stageProbability(st);
|
||||
const openDate =
|
||||
toDateOnly(o.open_date as string | null) ||
|
||||
toDateOnly(o.created_at as string | null) ||
|
||||
null;
|
||||
const expectedClose =
|
||||
toDateOnly(o.expected_close_date as string | null) ||
|
||||
toDateOnly(o.estimated_date as string | null) ||
|
||||
null;
|
||||
const actualClose = toDateOnly(o.actual_close_date as string | null);
|
||||
const annotated = annotateGroupOpportunity(
|
||||
{ ...o, stage: st, amount, probability },
|
||||
companyId,
|
||||
tree.names
|
||||
);
|
||||
return {
|
||||
...o,
|
||||
...annotated,
|
||||
name: o.name ?? null,
|
||||
contact_name: o.contact_name ?? null,
|
||||
company_name: o.company_name ?? null,
|
||||
contact_email: o.contact_email ?? null,
|
||||
product_interest: o.product_interest ?? null,
|
||||
stage: st,
|
||||
amount,
|
||||
probability,
|
||||
open_date: openDate,
|
||||
expected_close_date: expectedClose,
|
||||
actual_close_date: actualClose,
|
||||
contact_phone: o.contact_phone || o.contact_number || null,
|
||||
location: o.location || o.opportunity_location || null,
|
||||
description: o.description || o.notes || null,
|
||||
weighted_amount: Math.round((amount * probability) / 100),
|
||||
days_to_expected:
|
||||
openDate && expectedClose
|
||||
? Math.round(
|
||||
(new Date(expectedClose).getTime() -
|
||||
new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: null,
|
||||
days_to_close:
|
||||
openDate && actualClose
|
||||
? Math.round(
|
||||
(new Date(actualClose).getTime() -
|
||||
new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: null,
|
||||
days_open:
|
||||
openDate && !actualClose
|
||||
? Math.round(
|
||||
(Date.now() - new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: openDate && actualClose
|
||||
? Math.round(
|
||||
(new Date(actualClose).getTime() -
|
||||
new Date(openDate).getTime()) /
|
||||
(24 * 60 * 60 * 1000)
|
||||
)
|
||||
: null,
|
||||
};
|
||||
});
|
||||
|
||||
if (q) {
|
||||
opportunities = opportunities.filter((o) => {
|
||||
const hay = [
|
||||
searchHay(o.name),
|
||||
searchHay(o.contact_name),
|
||||
searchHay(o.company_name),
|
||||
searchHay(o.contact_email),
|
||||
searchHay(o.contact_phone),
|
||||
searchHay(o.stage),
|
||||
searchHay(o.product_interest),
|
||||
]
|
||||
.join(' ')
|
||||
.toLowerCase();
|
||||
return hay.includes(q);
|
||||
});
|
||||
}
|
||||
|
||||
const { summarizeGroupPipeline } = await import(
|
||||
'@/lib/business/group-pipeline-view'
|
||||
);
|
||||
const group = summarizeGroupPipeline({
|
||||
viewerCompanyId: companyId,
|
||||
names: tree.names,
|
||||
companyIds: tree.ids,
|
||||
isSubsidiary: tree.isSubsidiary,
|
||||
opportunities,
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
opportunities,
|
||||
group,
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
return NextResponse.json({ error: e instanceof Error ? e.message : 'Error' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
# Provenance: D-sorganization/Tools (fixed).
|
||||
# repo: D-sorganization/Tools
|
||||
# commit: a96bc0502a3dcdac303e4f0152508886e5c35c0a
|
||||
# parent: e735d28b82dd1fbc42c0ae01157b38d1b4c7c864
|
||||
# commit_url: https://github.com/D-sorganization/Tools/commit/a96bc0502a3dcdac303e4f0152508886e5c35c0a
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: _is_command_allowed
|
||||
# relpath: src/shared/python/ai/tools/cli_tools.py
|
||||
# provenance: agent
|
||||
# mechanism: source_reaches_sink
|
||||
|
||||
def _is_command_allowed(self, command: str) -> bool:
|
||||
"""Check if a command is allowed.
|
||||
|
||||
Args:
|
||||
command: Command to check.
|
||||
|
||||
Returns:
|
||||
True if allowed, False otherwise.
|
||||
"""
|
||||
# Dangerous commands are never allowed
|
||||
dangerous = ["rm", "sudo", "chmod", "chown", "curl", "wget", "ssh"]
|
||||
|
||||
# Prevent shell injection by blocking command separators/operators
|
||||
shell_operators = ["&&", "||", ";", "|", ">", "<", "$", "`", "\n", "&"]
|
||||
if any(op in command for op in shell_operators):
|
||||
return False
|
||||
|
||||
try:
|
||||
tokens = shlex.split(command)
|
||||
if not tokens:
|
||||
return False
|
||||
|
||||
# Verify the first token is in the allowlist
|
||||
base_cmd = tokens[0]
|
||||
if base_cmd not in self._allowed_commands:
|
||||
return False
|
||||
|
||||
# Verify no token is a dangerous command
|
||||
for token in tokens:
|
||||
if token in dangerous:
|
||||
return False
|
||||
|
||||
try:
|
||||
# Check for absolute/relative paths (e.g., /bin/rm, ./rm)
|
||||
if Path(token).name in dangerous:
|
||||
return False
|
||||
|
||||
# Check for assignments passing executables (e.g., --exec=/bin/rm)
|
||||
if "=" in token:
|
||||
val = token.split("=", 1)[1]
|
||||
if val in dangerous or Path(val).name in dangerous:
|
||||
return False
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return True
|
||||
except ValueError:
|
||||
# e.g., missing closing quote
|
||||
return False
|
||||
@@ -0,0 +1,48 @@
|
||||
# Provenance: D-sorganization/Tools (vuln).
|
||||
# repo: D-sorganization/Tools
|
||||
# commit: e735d28b82dd1fbc42c0ae01157b38d1b4c7c864
|
||||
# parent: e735d28b82dd1fbc42c0ae01157b38d1b4c7c864
|
||||
# commit_url: https://github.com/D-sorganization/Tools/commit/a96bc0502a3dcdac303e4f0152508886e5c35c0a
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: _is_command_allowed
|
||||
# relpath: src/shared/python/ai/tools/cli_tools.py
|
||||
# provenance: agent
|
||||
# mechanism: source_reaches_sink
|
||||
|
||||
def _is_command_allowed(self, command: str) -> bool:
|
||||
"""Check if a command is allowed.
|
||||
|
||||
Args:
|
||||
command: Command to check.
|
||||
|
||||
Returns:
|
||||
True if allowed, False otherwise.
|
||||
"""
|
||||
# Dangerous commands are never allowed
|
||||
dangerous = ["rm", "sudo", "chmod", "chown", "curl", "wget", "ssh"]
|
||||
|
||||
# Prevent shell injection by blocking command separators/operators
|
||||
shell_operators = ["&&", "||", ";", "|", ">", "<", "$", "`", "\n", "&"]
|
||||
if any(op in command for op in shell_operators):
|
||||
return False
|
||||
|
||||
try:
|
||||
tokens = shlex.split(command)
|
||||
if not tokens:
|
||||
return False
|
||||
|
||||
# Verify the first token is in the allowlist
|
||||
base_cmd = tokens[0]
|
||||
if base_cmd not in self._allowed_commands:
|
||||
return False
|
||||
|
||||
# Verify no token is a dangerous command
|
||||
for token in tokens:
|
||||
if token in dangerous:
|
||||
return False
|
||||
|
||||
return True
|
||||
except ValueError:
|
||||
# e.g., missing closing quote
|
||||
return False
|
||||
@@ -0,0 +1,48 @@
|
||||
// Provenance: trackly-app/trackly-cli (fixed).
|
||||
// repo: trackly-app/trackly-cli
|
||||
// commit: 1c1aed89b07edb04051830c8f086e02b65e961c6
|
||||
// parent: 8d240ad8d7fc114c8f941ad956a2fdf32391ff60
|
||||
// commit_url: https://github.com/trackly-app/trackly-cli/commit/1c1aed89b07edb04051830c8f086e02b65e961c6
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: inspectExistingAncestor
|
||||
// relpath: lib/path-diagnostics.js
|
||||
// provenance: agent
|
||||
// mechanism: path_join_user_input
|
||||
|
||||
async function inspectExistingAncestor(exactPath, stat = fs.stat) {
|
||||
let candidate = exactPath;
|
||||
while (true) {
|
||||
try {
|
||||
const stats = await stat(candidate);
|
||||
return {
|
||||
ancestor: candidate,
|
||||
exactPathExists: candidate === exactPath,
|
||||
exactPathType: candidate === exactPath ? (stats.isDirectory() ? 'directory' : 'file') : null,
|
||||
writableDirectory: stats.isDirectory() ? candidate : path.dirname(candidate),
|
||||
inspectionErrorCode: null,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') {
|
||||
return {
|
||||
ancestor: candidate,
|
||||
exactPathExists: null,
|
||||
exactPathType: null,
|
||||
writableDirectory: null,
|
||||
inspectionErrorCode: error.code || 'path_inspection_failed',
|
||||
};
|
||||
}
|
||||
const parent = path.dirname(candidate);
|
||||
if (parent === candidate) {
|
||||
return {
|
||||
ancestor: parent,
|
||||
exactPathExists: false,
|
||||
exactPathType: null,
|
||||
writableDirectory: parent,
|
||||
inspectionErrorCode: null,
|
||||
};
|
||||
}
|
||||
candidate = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Provenance: trackly-app/trackly-cli (vuln).
|
||||
// repo: trackly-app/trackly-cli
|
||||
// commit: 8d240ad8d7fc114c8f941ad956a2fdf32391ff60
|
||||
// parent: 8d240ad8d7fc114c8f941ad956a2fdf32391ff60
|
||||
// commit_url: https://github.com/trackly-app/trackly-cli/commit/1c1aed89b07edb04051830c8f086e02b65e961c6
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: inspectExistingAncestor
|
||||
// relpath: lib/path-diagnostics.js
|
||||
// provenance: agent
|
||||
// mechanism: path_join_user_input
|
||||
|
||||
async function inspectExistingAncestor(exactPath) {
|
||||
let candidate = exactPath;
|
||||
while (true) {
|
||||
try {
|
||||
const stats = await fs.stat(candidate);
|
||||
return {
|
||||
ancestor: candidate,
|
||||
exactPathExists: candidate === exactPath,
|
||||
exactPathType: candidate === exactPath ? (stats.isDirectory() ? 'directory' : 'file') : null,
|
||||
writableDirectory: stats.isDirectory() ? candidate : path.dirname(candidate),
|
||||
};
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') throw error;
|
||||
const parent = path.dirname(candidate);
|
||||
if (parent === candidate) {
|
||||
return { ancestor: parent, exactPathExists: false, exactPathType: null, writableDirectory: parent };
|
||||
}
|
||||
candidate = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# Provenance: D-sorganization/UpstreamDrift (fixed).
|
||||
# repo: D-sorganization/UpstreamDrift
|
||||
# commit: c3a0787080489b30e2ed0abfac03b51e45da184b
|
||||
# parent: e28d1da5e103d93951ef11b78a6e9b89ac1fa2bc
|
||||
# commit_url: https://github.com/D-sorganization/UpstreamDrift/commit/c3a0787080489b30e2ed0abfac03b51e45da184b
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: _find_logo_file
|
||||
# relpath: src/api/local_server.py
|
||||
# provenance: agent
|
||||
# mechanism: path_join_user_input
|
||||
|
||||
def _find_logo_file(logo_name: str) -> Path | None:
|
||||
"""Search for a logo file in known asset directories.
|
||||
|
||||
The caller-supplied ``logo_name`` is joined onto each candidate root via
|
||||
:func:`_safe_join` so that ``..`` traversal, absolute paths, and symlink
|
||||
escape are rejected before touching the filesystem.
|
||||
|
||||
Args:
|
||||
logo_name: Filename of the logo to find.
|
||||
|
||||
Returns:
|
||||
Path to the logo file, or None if not found or rejected as unsafe.
|
||||
"""
|
||||
for root in (
|
||||
Path(__file__).parent.parent.parent / "assets" / "logos",
|
||||
Path(__file__).parent.parent / "launchers" / "assets",
|
||||
):
|
||||
resolved = _safe_join(root, logo_name)
|
||||
if resolved is not None and resolved.exists() and resolved.is_file():
|
||||
return resolved
|
||||
return None
|
||||
@@ -0,0 +1,30 @@
|
||||
# Provenance: D-sorganization/UpstreamDrift (vuln).
|
||||
# repo: D-sorganization/UpstreamDrift
|
||||
# commit: e28d1da5e103d93951ef11b78a6e9b89ac1fa2bc
|
||||
# parent: e28d1da5e103d93951ef11b78a6e9b89ac1fa2bc
|
||||
# commit_url: https://github.com/D-sorganization/UpstreamDrift/commit/c3a0787080489b30e2ed0abfac03b51e45da184b
|
||||
# cve:
|
||||
# license: MIT
|
||||
# function: _find_logo_file
|
||||
# relpath: src/api/local_server.py
|
||||
# provenance: agent
|
||||
# mechanism: path_join_user_input
|
||||
|
||||
def _find_logo_file(logo_name: str) -> Path | None:
|
||||
"""Search for a logo file in known asset directories.
|
||||
|
||||
Args:
|
||||
logo_name: Filename of the logo to find.
|
||||
|
||||
Returns:
|
||||
Path to the logo file, or None if not found.
|
||||
"""
|
||||
logos_dir = Path(__file__).parent.parent.parent / "assets" / "logos"
|
||||
logo_path = logos_dir / logo_name
|
||||
if logo_path.exists() and logo_path.is_file():
|
||||
return logo_path
|
||||
launcher_logos = Path(__file__).parent.parent / "launchers" / "assets"
|
||||
alt_path = launcher_logos / logo_name
|
||||
if alt_path.exists() and alt_path.is_file():
|
||||
return alt_path
|
||||
return None
|
||||
@@ -0,0 +1,28 @@
|
||||
# Provenance: Ahkeratmehilaiset/waggledance-swarm (fixed).
|
||||
# repo: Ahkeratmehilaiset/waggledance-swarm
|
||||
# commit: 9a454843aa35332ff2eb3106023eee0c4b5e444b
|
||||
# parent: 934b939f1cca5259eaf807db3319eb97b90d8d80
|
||||
# commit_url: https://github.com/Ahkeratmehilaiset/waggledance-swarm/commit/9a454843aa35332ff2eb3106023eee0c4b5e444b
|
||||
# cve:
|
||||
# license: Apache-2.0
|
||||
# function: normalize_allowed_hosts
|
||||
# relpath: waggledance/core/v3_13_0/ssrf_host_guard.py
|
||||
# provenance: agent
|
||||
# mechanism: source_reaches_sink
|
||||
|
||||
def normalize_allowed_hosts(raw_hosts: Iterable[str]) -> frozenset[str]:
|
||||
"""Validate and canonicalize an exact-host allowlist."""
|
||||
if (
|
||||
not isinstance(raw_hosts, Iterable)
|
||||
or isinstance(raw_hosts, (str, bytes, Mapping))
|
||||
):
|
||||
raise ValueError("ALLOWLIST_HOSTS_REFUSED")
|
||||
normalized: set[str] = set()
|
||||
for index, host in enumerate(raw_hosts):
|
||||
if not isinstance(host, str) or not host.strip():
|
||||
raise ValueError(f"ALLOWLIST_HOSTS_REFUSED_{index}")
|
||||
clean = normalize_host(host)
|
||||
if "://" in clean or "/" in clean or "?" in clean or "@" in clean:
|
||||
raise ValueError(f"ALLOWLIST_HOSTS_REFUSED_{index}")
|
||||
normalized.add(clean)
|
||||
return frozenset(normalized)
|
||||
@@ -0,0 +1,25 @@
|
||||
# Provenance: Ahkeratmehilaiset/waggledance-swarm (vuln).
|
||||
# repo: Ahkeratmehilaiset/waggledance-swarm
|
||||
# commit: 934b939f1cca5259eaf807db3319eb97b90d8d80
|
||||
# parent: 934b939f1cca5259eaf807db3319eb97b90d8d80
|
||||
# commit_url: https://github.com/Ahkeratmehilaiset/waggledance-swarm/commit/9a454843aa35332ff2eb3106023eee0c4b5e444b
|
||||
# cve:
|
||||
# license: Apache-2.0
|
||||
# function: normalize_allowed_hosts
|
||||
# relpath: waggledance/core/v3_13_0/ssrf_host_guard.py
|
||||
# provenance: agent
|
||||
# mechanism: source_reaches_sink
|
||||
|
||||
def normalize_allowed_hosts(raw_hosts: Sequence[str]) -> frozenset[str]:
|
||||
"""Validate and canonicalize an exact-host allowlist."""
|
||||
if not isinstance(raw_hosts, Sequence) or isinstance(raw_hosts, (str, bytes)):
|
||||
raise ValueError("ALLOWLIST_HOSTS_REFUSED")
|
||||
normalized: set[str] = set()
|
||||
for index, host in enumerate(raw_hosts):
|
||||
if not isinstance(host, str) or not host.strip():
|
||||
raise ValueError(f"ALLOWLIST_HOSTS_REFUSED_{index}")
|
||||
clean = normalize_host(host)
|
||||
if "://" in clean or "/" in clean or "?" in clean or "@" in clean:
|
||||
raise ValueError(f"ALLOWLIST_HOSTS_REFUSED_{index}")
|
||||
normalized.add(clean)
|
||||
return frozenset(normalized)
|
||||
@@ -0,0 +1,162 @@
|
||||
// Provenance: G4brym/workers-research (fixed).
|
||||
// repo: G4brym/workers-research
|
||||
// commit: 209444eb61cc564c2d6b43267256f85fe3e5e30e
|
||||
// parent: eab923ad3099c01b002fbd6be7cf994614bbdee4
|
||||
// commit_url: https://github.com/G4brym/workers-research/commit/209444eb61cc564c2d6b43267256f85fe3e5e30e
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: formatDuration
|
||||
// relpath: src/utils.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
import {
|
||||
createGoogleGenerativeAI,
|
||||
type GoogleGenerativeAIProvider,
|
||||
type GoogleGenerativeAIProviderSettings,
|
||||
} from "@ai-sdk/google";
|
||||
import type { Env } from "./bindings";
|
||||
|
||||
function getGoogleProvider(env: Env): GoogleGenerativeAIProvider {
|
||||
const args: GoogleGenerativeAIProviderSettings = {
|
||||
apiKey: env.GOOGLE_API_KEY,
|
||||
};
|
||||
|
||||
if (env.AI_GATEWAY_ACCOUNT_ID && env.AI_GATEWAY_NAME) {
|
||||
args.baseURL = `https://gateway.ai.cloudflare.com/v1/${env.AI_GATEWAY_ACCOUNT_ID}/${env.AI_GATEWAY_NAME}/google-ai-studio/v1beta`;
|
||||
|
||||
if (env.AI_GATEWAY_API_KEY) {
|
||||
args.headers = {
|
||||
"cf-aig-authorization": `Bearer ${env.AI_GATEWAY_API_KEY}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return createGoogleGenerativeAI(args);
|
||||
}
|
||||
|
||||
export function getModel(env: Env) {
|
||||
const google = getGoogleProvider(env);
|
||||
|
||||
return google("gemini-2.0-flash-exp");
|
||||
}
|
||||
|
||||
export function getFallbackModel(env: Env) {
|
||||
const google = getGoogleProvider(env);
|
||||
return google("gemini-2.0-flash");
|
||||
}
|
||||
|
||||
export function getModelThinking(env: Env) {
|
||||
const google = getGoogleProvider(env);
|
||||
|
||||
return google("gemini-2.0-flash-exp");
|
||||
}
|
||||
|
||||
export function timeAgo(date: Date): string {
|
||||
const now = new Date();
|
||||
const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
||||
|
||||
const intervals: [number, string][] = [
|
||||
[60, "minute"],
|
||||
[60, "hour"],
|
||||
[24, "day"],
|
||||
[7, "week"],
|
||||
[4.35, "month"],
|
||||
[12, "year"],
|
||||
];
|
||||
|
||||
let count = seconds;
|
||||
let unit = "second";
|
||||
|
||||
for (const [interval, name] of intervals) {
|
||||
if (count < interval) break;
|
||||
count /= interval;
|
||||
unit = name;
|
||||
}
|
||||
|
||||
count = Math.floor(count);
|
||||
return `${count} ${unit}${count !== 1 ? "s" : ""} ago`;
|
||||
}
|
||||
|
||||
export async function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a domain input for excluded domain matching.
|
||||
* Handles common user input formats:
|
||||
* - Full URLs: "https://reddit.com/foo" → "reddit.com"
|
||||
* - www prefix: "www.reddit.com" → "reddit.com"
|
||||
* - Mixed: "https://www.reddit.com" → "reddit.com"
|
||||
* - Plain domains are returned as-is (lowercased, trimmed)
|
||||
*/
|
||||
export function normalizeDomain(input: string): string {
|
||||
let domain = input.trim().toLowerCase();
|
||||
if (domain.length === 0) return "";
|
||||
|
||||
// If it looks like a URL (has ://), extract the hostname
|
||||
if (domain.includes("://")) {
|
||||
try {
|
||||
domain = new URL(domain).hostname;
|
||||
} catch {
|
||||
// If URL parsing fails, strip the protocol manually
|
||||
domain = domain.replace(/^[a-z]+:\/\//, "").split("/")[0];
|
||||
}
|
||||
} else {
|
||||
// Strip any trailing path from plain domain input
|
||||
domain = domain.split("/")[0];
|
||||
}
|
||||
|
||||
// Strip www. prefix for consistent matching
|
||||
domain = domain.replace(/^www\./, "");
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build parameterized search filter conditions for research list queries.
|
||||
* Uses parameterized queries to prevent SQL injection.
|
||||
*/
|
||||
export function buildSearchFilters(
|
||||
q?: string,
|
||||
status?: string,
|
||||
): { conditions: string[]; params: (string | number)[] } {
|
||||
const conditions: string[] = [];
|
||||
const params: (string | number)[] = [];
|
||||
|
||||
if (q?.trim()) {
|
||||
const searchTerm = `%${q.trim()}%`;
|
||||
conditions.push("(title LIKE ? OR query LIKE ?)");
|
||||
params.push(searchTerm, searchTerm);
|
||||
}
|
||||
|
||||
if (status && ["1", "2", "3"].includes(status)) {
|
||||
conditions.push("status = ?");
|
||||
params.push(Number.parseInt(status, 10));
|
||||
}
|
||||
|
||||
return { conditions, params };
|
||||
}
|
||||
|
||||
export function formatDuration(ms: number): string {
|
||||
// Handle negative or zero values
|
||||
if (ms <= 0) {
|
||||
return "0.0 seconds";
|
||||
}
|
||||
|
||||
const seconds = ms / 1000;
|
||||
const minutes = seconds / 60;
|
||||
const hours = minutes / 60;
|
||||
const days = hours / 24;
|
||||
|
||||
// Determine the appropriate unit and format with one decimal place
|
||||
if (days >= 1) {
|
||||
return `${days.toFixed(1)} day${days !== 1 ? "s" : ""}`;
|
||||
} else if (hours >= 1) {
|
||||
return `${hours.toFixed(1)} hour${hours !== 1 ? "s" : ""}`;
|
||||
} else if (minutes >= 1) {
|
||||
return `${minutes.toFixed(1)} minute${minutes !== 1 ? "s" : ""}`;
|
||||
} else {
|
||||
return `${seconds.toFixed(1)} second${seconds !== 1 ? "s" : ""}`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
// Provenance: G4brym/workers-research (vuln).
|
||||
// repo: G4brym/workers-research
|
||||
// commit: eab923ad3099c01b002fbd6be7cf994614bbdee4
|
||||
// parent: eab923ad3099c01b002fbd6be7cf994614bbdee4
|
||||
// commit_url: https://github.com/G4brym/workers-research/commit/209444eb61cc564c2d6b43267256f85fe3e5e30e
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: formatDuration
|
||||
// relpath: src/utils.ts
|
||||
// provenance: agent
|
||||
// mechanism: source_reaches_sink
|
||||
|
||||
import {
|
||||
createGoogleGenerativeAI,
|
||||
type GoogleGenerativeAIProvider,
|
||||
type GoogleGenerativeAIProviderSettings,
|
||||
} from "@ai-sdk/google";
|
||||
import type { Env } from "./bindings";
|
||||
|
||||
function getGoogleProvider(env: Env): GoogleGenerativeAIProvider {
|
||||
const args: GoogleGenerativeAIProviderSettings = {
|
||||
apiKey: env.GOOGLE_API_KEY,
|
||||
};
|
||||
|
||||
if (env.AI_GATEWAY_ACCOUNT_ID && env.AI_GATEWAY_NAME) {
|
||||
args.baseURL = `https://gateway.ai.cloudflare.com/v1/${env.AI_GATEWAY_ACCOUNT_ID}/${env.AI_GATEWAY_NAME}/google-ai-studio/v1beta`;
|
||||
|
||||
if (env.AI_GATEWAY_API_KEY) {
|
||||
args.headers = {
|
||||
"cf-aig-authorization": `Bearer ${env.AI_GATEWAY_API_KEY}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return createGoogleGenerativeAI(args);
|
||||
}
|
||||
|
||||
export function getModel(env: Env) {
|
||||
const google = getGoogleProvider(env);
|
||||
|
||||
return google("gemini-2.0-flash-exp");
|
||||
}
|
||||
|
||||
export function getFallbackModel(env: Env) {
|
||||
const google = getGoogleProvider(env);
|
||||
return google("gemini-2.0-flash");
|
||||
}
|
||||
|
||||
export function getModelThinking(env: Env) {
|
||||
const google = getGoogleProvider(env);
|
||||
|
||||
return google("gemini-2.0-flash-exp");
|
||||
}
|
||||
|
||||
export function timeAgo(date: Date): string {
|
||||
const now = new Date();
|
||||
const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
||||
|
||||
const intervals: [number, string][] = [
|
||||
[60, "minute"],
|
||||
[60, "hour"],
|
||||
[24, "day"],
|
||||
[7, "week"],
|
||||
[4.35, "month"],
|
||||
[12, "year"],
|
||||
];
|
||||
|
||||
let count = seconds;
|
||||
let unit = "second";
|
||||
|
||||
for (const [interval, name] of intervals) {
|
||||
if (count < interval) break;
|
||||
count /= interval;
|
||||
unit = name;
|
||||
}
|
||||
|
||||
count = Math.floor(count);
|
||||
return `${count} ${unit}${count !== 1 ? "s" : ""} ago`;
|
||||
}
|
||||
|
||||
export async function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a domain input for excluded domain matching.
|
||||
* Handles common user input formats:
|
||||
* - Full URLs: "https://reddit.com/foo" → "reddit.com"
|
||||
* - www prefix: "www.reddit.com" → "reddit.com"
|
||||
* - Mixed: "https://www.reddit.com" → "reddit.com"
|
||||
* - Plain domains are returned as-is (lowercased, trimmed)
|
||||
*/
|
||||
export function normalizeDomain(input: string): string {
|
||||
let domain = input.trim().toLowerCase();
|
||||
if (domain.length === 0) return "";
|
||||
|
||||
// If it looks like a URL (has ://), extract the hostname
|
||||
if (domain.includes("://")) {
|
||||
try {
|
||||
domain = new URL(domain).hostname;
|
||||
} catch {
|
||||
// If URL parsing fails, strip the protocol manually
|
||||
domain = domain.replace(/^[a-z]+:\/\//, "").split("/")[0];
|
||||
}
|
||||
} else {
|
||||
// Strip any trailing path from plain domain input
|
||||
domain = domain.split("/")[0];
|
||||
}
|
||||
|
||||
// Strip www. prefix for consistent matching
|
||||
domain = domain.replace(/^www\./, "");
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
export function formatDuration(ms: number): string {
|
||||
// Handle negative or zero values
|
||||
if (ms <= 0) {
|
||||
return "0.0 seconds";
|
||||
}
|
||||
|
||||
const seconds = ms / 1000;
|
||||
const minutes = seconds / 60;
|
||||
const hours = minutes / 60;
|
||||
const days = hours / 24;
|
||||
|
||||
// Determine the appropriate unit and format with one decimal place
|
||||
if (days >= 1) {
|
||||
return `${days.toFixed(1)} day${days !== 1 ? "s" : ""}`;
|
||||
} else if (hours >= 1) {
|
||||
return `${hours.toFixed(1)} hour${hours !== 1 ? "s" : ""}`;
|
||||
} else if (minutes >= 1) {
|
||||
return `${minutes.toFixed(1)} minute${minutes !== 1 ? "s" : ""}`;
|
||||
} else {
|
||||
return `${seconds.toFixed(1)} second${seconds !== 1 ? "s" : ""}`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Provenance: zoonk/zoonk (fixed).
|
||||
// repo: zoonk/zoonk
|
||||
// commit: bfbf670ccb41d63c407d32c51bd26e626a174f31
|
||||
// parent: 2604269350bff51f58572c133b45010cb0976a5a
|
||||
// commit_url: https://github.com/zoonk/zoonk/commit/bfbf670ccb41d63c407d32c51bd26e626a174f31
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: getAllowedHosts
|
||||
// relpath: packages/utils/src/origin.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export function getAllowedHosts(): string[] {
|
||||
return [
|
||||
...ZOONK_DOMAINS.flatMap((domain) => [domain, `*.${domain}`]),
|
||||
...(isLocalhostSupported() ? ["localhost:*"] : []),
|
||||
...(canAcceptVercelPreviewOrigins() ? [ZOONK_VERCEL_PREVIEW_HOST] : []),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Provenance: zoonk/zoonk (vuln).
|
||||
// repo: zoonk/zoonk
|
||||
// commit: 2604269350bff51f58572c133b45010cb0976a5a
|
||||
// parent: 2604269350bff51f58572c133b45010cb0976a5a
|
||||
// commit_url: https://github.com/zoonk/zoonk/commit/bfbf670ccb41d63c407d32c51bd26e626a174f31
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: getAllowedHosts
|
||||
// relpath: packages/utils/src/origin.ts
|
||||
// provenance: agent
|
||||
// mechanism: permissive_default
|
||||
|
||||
export function getAllowedHosts(): string[] {
|
||||
return [
|
||||
...ZOONK_DOMAINS.flatMap((domain) => [domain, `*.${domain}`]),
|
||||
...(isLocalhostSupported() ? ["localhost:*"] : []),
|
||||
...(getEnvironment() === "production" ? [] : ["*-zoonk.vercel.app"]),
|
||||
];
|
||||
}
|
||||
@@ -151,3 +151,63 @@ url = "https://github.com/curl/curl"
|
||||
level = "commit/function"
|
||||
languages = ["C"]
|
||||
notes = "Public git. Seed: CVE-2023-38545 do_SOCKS5. Isolated functions only; do not vendor the tree."
|
||||
|
||||
# --- pair-corpus-honesty: web, agent-authored, and LLM-generated corpora ---
|
||||
|
||||
[[dataset]]
|
||||
name = "Real-Vuln-Benchmark"
|
||||
url = "https://github.com/kolega-ai/Real-Vuln-Benchmark"
|
||||
data = "benchmarks/pairs/vibe-py"
|
||||
level = "repo/function/line"
|
||||
languages = ["Python"]
|
||||
notes = "Apache-2.0 (v2). 66 pinned Python web repos: 26 human-authored, 40 LLM-generated (Claude, GPT, Kimi) seeded with reviewed vulns. 1896 vulnerable findings + 280 false-positive traps with file, line range, function, primary/acceptable CWEs, severity, authorship. Educational/CTF style, not production. Source of the `vibe-py` slice; traps are the fixed-side twins."
|
||||
|
||||
[[dataset]]
|
||||
name = "SecBench.js"
|
||||
url = "https://github.com/cristianstaicu/SecBench.js"
|
||||
level = "package/sink-line"
|
||||
languages = ["JavaScript"]
|
||||
notes = "600 real npm vulnerabilities (prototype pollution, ReDoS, command injection, path traversal, code injection) with Jest exploit oracles, fixCommit, fixedVersion, and sinkLocation. No license file: never vendor its test files; harvest function pairs from the upstream package repositories named in fixCommit (`vfc-js` slice) and record each package's own license."
|
||||
|
||||
[[dataset]]
|
||||
name = "AIDev"
|
||||
url = "https://huggingface.co/datasets/hao-li/AIDev"
|
||||
level = "pull request"
|
||||
languages = ["multi"]
|
||||
notes = "932k agent-authored PRs (Claude Code, Codex, Copilot, Cursor, Devin, Jules) with patches and language; CC-BY-4.0 index, source repos keep their licenses. No security labels. Candidate source for `agent-vfc` together with GitHub commit search on agent co-author trailers."
|
||||
|
||||
[[dataset]]
|
||||
name = "BaxBench"
|
||||
url = "https://github.com/logic-star-ai/baxbench"
|
||||
data = "https://huggingface.co/datasets/LogicStar/BaxBench"
|
||||
level = "scenario/exploit"
|
||||
languages = ["Python", "JavaScript", "TypeScript", "Go", "Rust", "PHP"]
|
||||
notes = "MIT. 28 backend scenarios x 14 frameworks (Express, Flask, FastAPI, Django, Nest, ...) with functional tests and executable exploits per CWE. Generated code is not shipped; generate with any model, the exploit harness labels each sample. Deferred slice (`baxgen`) until deep mode can run its exploits."
|
||||
|
||||
[[dataset]]
|
||||
name = "SecurityEval"
|
||||
url = "https://github.com/s2e-lab/SecurityEval"
|
||||
level = "prompt/sample"
|
||||
languages = ["Python"]
|
||||
notes = "121 prompts over 69 CWEs with Copilot and InCoder outputs. Vibe-textbook only; not web recall."
|
||||
|
||||
[[dataset]]
|
||||
name = "CodeSecEval"
|
||||
url = "https://arxiv.org/abs/2407.02395"
|
||||
level = "sample"
|
||||
languages = ["Python"]
|
||||
notes = "180 samples, 44 vulnerability types, insecure and secure executable code with tests. Pointer only."
|
||||
|
||||
[[dataset]]
|
||||
name = "CWEval"
|
||||
url = "https://github.com/Co1lin/CWEval"
|
||||
level = "task"
|
||||
languages = ["C", "Python", "JavaScript"]
|
||||
notes = "Functionality plus security evaluation of LLM-generated code on the same tasks. Pointer only."
|
||||
|
||||
[[dataset]]
|
||||
name = "CyberSecEval insecure code"
|
||||
url = "https://github.com/meta-llama/PurpleLlama/tree/main/CybersecurityBenchmarks"
|
||||
level = "test case"
|
||||
languages = ["C", "C++", "C#", "Java", "JavaScript", "PHP", "Python", "Rust"]
|
||||
notes = "MIT. Labels are DEFINED by its Insecure Code Detector regex/semgrep/weggli rules. Circular for a rule-proposing tool: coverage pointer only, never recall ground truth."
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# Closed mechanism vocabulary for pair labels (pair-corpus-honesty, Req 2.1).
|
||||
# Every [[pair.expected]] row names one of these ids. Bump `version` when the set changes.
|
||||
version = "1"
|
||||
|
||||
[[mechanism]]
|
||||
id = "source_reaches_sink"
|
||||
definition = "A fact-listed source flows by name into a fact-listed sink without a sanitizer."
|
||||
|
||||
[[mechanism]]
|
||||
id = "container_taint"
|
||||
definition = "Taint travels through a mutable container or config object (list.append, dict[key], ConfigParser.set/get) before the sink."
|
||||
|
||||
[[mechanism]]
|
||||
id = "config_sink_weak_literal"
|
||||
definition = "A configuration sink is dangerous because of a literal argument (hashlib.new('md5'), MessageDigest 'SHA-1', debug=True)."
|
||||
|
||||
[[mechanism]]
|
||||
id = "unchecked_length_copy"
|
||||
definition = "A copy or read uses a length or index that is not bounded by a dominating check."
|
||||
|
||||
[[mechanism]]
|
||||
id = "unchecked_alloc_size"
|
||||
definition = "An allocation size derives from untrusted or unbounded input."
|
||||
|
||||
[[mechanism]]
|
||||
id = "null_deref_unguarded"
|
||||
definition = "A pointer that may be NULL is dereferenced without a dominating NULL test."
|
||||
|
||||
[[mechanism]]
|
||||
id = "signed_size_operand"
|
||||
definition = "A signed or narrower type feeds a size or length operand and can wrap."
|
||||
|
||||
[[mechanism]]
|
||||
id = "fixed_buffer_capacity"
|
||||
definition = "A fixed-size buffer receives data larger than its declared capacity."
|
||||
|
||||
[[mechanism]]
|
||||
id = "identity_from_request_body"
|
||||
definition = "A user or owner identity is taken from the request body or query instead of the authenticated context."
|
||||
|
||||
[[mechanism]]
|
||||
id = "missing_auth_guard"
|
||||
definition = "A route or handler performs a privileged action with no authentication or authorization guard on its path."
|
||||
|
||||
[[mechanism]]
|
||||
id = "secret_in_client"
|
||||
definition = "A secret or privileged key is shipped to client-side code or committed configuration."
|
||||
|
||||
[[mechanism]]
|
||||
id = "permissive_default"
|
||||
definition = "A security control is left at a permissive default (RLS off, CORS wildcard, debug mode, open bucket)."
|
||||
|
||||
[[mechanism]]
|
||||
id = "path_join_user_input"
|
||||
definition = "A filesystem path is built from user input without normalization or containment."
|
||||
|
||||
[[mechanism]]
|
||||
id = "prototype_pollution"
|
||||
definition = "Attacker-controlled keys reach a recursive merge or assignment that writes Object.prototype."
|
||||
|
||||
[[mechanism]]
|
||||
id = "redos"
|
||||
definition = "A regular expression with catastrophic backtracking is applied to untrusted input."
|
||||
|
||||
[[mechanism]]
|
||||
id = "uaf"
|
||||
definition = "Memory is used after it was released."
|
||||
|
||||
[[mechanism]]
|
||||
id = "type_confusion"
|
||||
definition = "A value is interpreted as a type it is not."
|
||||
|
||||
[[mechanism]]
|
||||
id = "validation_strength"
|
||||
definition = "A validator exists but accepts inputs it should reject; the fix strengthens the check."
|
||||
|
||||
[[mechanism]]
|
||||
id = "cross_artifact"
|
||||
definition = "The bug is only decidable with an artifact outside the vendored files (a properties file, a schema, a build flag)."
|
||||
|
||||
[[mechanism]]
|
||||
id = "other"
|
||||
definition = "Not yet classified. Present so bulk-mined pairs load; review should replace it."
|
||||
@@ -0,0 +1,14 @@
|
||||
# vfc-js slice
|
||||
|
||||
Server-side JavaScript function pairs harvested from the **upstream fix commits** that
|
||||
[SecBench.js](https://github.com/cristianstaicu/SecBench.js) records in its package metadata
|
||||
(`fixCommit`, `sink`). SecBench.js itself has no license file, so none of its files are vendored;
|
||||
each excerpt carries the upstream package's license.
|
||||
|
||||
- Classes: command injection, path traversal, code injection first. Prototype pollution and ReDoS
|
||||
rows may be added with their own mechanism and `known_limit` until the engine can talk about them.
|
||||
- Mode: `hunk` (the function enclosing the first changed hunk on each side).
|
||||
- Provenance: `human`.
|
||||
|
||||
Rebuild: `python benchmarks/pairs/vfc-js/build_recipes.py --crawl /tmp/secbench.jsonl` then
|
||||
`--from /tmp/secbench.jsonl`, `harvest.py --slice vfc-js --all --fetch`, `catalog_gen.py --slice vfc-js`.
|
||||
@@ -0,0 +1,55 @@
|
||||
// Provenance: simonh1000/angular-http-server (fixed).
|
||||
// repo: simonh1000/angular-http-server
|
||||
// commit: 8bafc9577161469f5dea01e0b98ea9c525d063e9
|
||||
// parent: d171a771a92e4685b24fb77cb894a7b7b8024c5c
|
||||
// commit_url: https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: requestListener
|
||||
// relpath: angular-http-server.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 45
|
||||
|
||||
function requestListener(req, res) {
|
||||
// Add CORS header if option chosen
|
||||
if (argv.cors) {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Request-Method', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
|
||||
// When the request is for CORS OPTIONS (rather than a page) return just the headers
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Request is for a page instead
|
||||
// Only interested in the part before any query params
|
||||
var url = req.url.split('?')[0]
|
||||
// Attaches path prefix with --path option
|
||||
var possibleFilename = resolveUrl(url.slice(1)) || "dummy";
|
||||
|
||||
var safeFileName = path.normalize(possibleFilename).replace(/^(\.\.[\/\\])+/, '');
|
||||
var safeFullFilename = path.join(__dirname, safeFileName);
|
||||
|
||||
fs.stat(safeFullFilename, function(err, stats) {
|
||||
var fileBuffer;
|
||||
if (!err && stats.isFile()) {
|
||||
fileBuffer = fs.readFileSync(safeFullFilename);
|
||||
let ct = mime.lookup(safeFullFilename);
|
||||
log(`Sending ${safeFullFilename} with Content-Type ${ct}`);
|
||||
res.writeHead(200, { 'Content-Type': ct });
|
||||
|
||||
} else {
|
||||
log("Route %s, replacing with index.html", safeFullFilename);
|
||||
fileBuffer = returnDistFile();
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
}
|
||||
|
||||
res.write(fileBuffer);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Provenance: simonh1000/angular-http-server (vuln).
|
||||
// repo: simonh1000/angular-http-server
|
||||
// commit: d171a771a92e4685b24fb77cb894a7b7b8024c5c
|
||||
// parent: d171a771a92e4685b24fb77cb894a7b7b8024c5c
|
||||
// commit_url: https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: requestListener
|
||||
// relpath: angular-http-server.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 45
|
||||
|
||||
function requestListener(req, res) {
|
||||
// Add CORS header if option chosen
|
||||
if (argv.cors) {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Request-Method', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
|
||||
// When the request is for CORS OPTIONS (rather than a page) return just the headers
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Request is for a page instead
|
||||
// Only interested in the part before any query params
|
||||
var url = req.url.split('?')[0]
|
||||
// Attaches path prefix with --path option
|
||||
var possibleFilename = resolveUrl(url.slice(1)) || "dummy";
|
||||
|
||||
fs.stat(possibleFilename, function(err, stats) {
|
||||
var fileBuffer;
|
||||
if (!err && stats.isFile()) {
|
||||
fileBuffer = fs.readFileSync(possibleFilename);
|
||||
let ct = mime.lookup(possibleFilename);
|
||||
log(`Sending ${possibleFilename} with Content-Type ${ct}`);
|
||||
res.writeHead(200, { 'Content-Type': ct });
|
||||
|
||||
} else {
|
||||
log("Route %s, replacing with index.html", possibleFilename);
|
||||
fileBuffer = returnDistFile();
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
}
|
||||
|
||||
res.write(fileBuffer);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Provenance: vincentmorneau/apex-publish-static-files (fixed).
|
||||
// repo: vincentmorneau/apex-publish-static-files
|
||||
// commit: 2209af8f2b65c24aa55ab757e0e05b958c16f063
|
||||
// parent: 8d28fe8a9a49e5ff3f61e239293b5646528e2915
|
||||
// commit_url: https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063
|
||||
// cve: CVE-2018-16462
|
||||
// license: MIT
|
||||
// function: publish
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 7
|
||||
|
||||
module.exports = {
|
||||
// Validates a JSON object
|
||||
publish(opts) {
|
||||
// Set defaults
|
||||
const defaults = {
|
||||
sqlclPath: 'sql',
|
||||
destination: 'application'
|
||||
};
|
||||
opts = Object.assign(defaults, opts);
|
||||
|
||||
// Validate arguments
|
||||
if (typeof opts.connectString === 'undefined') {
|
||||
throw new TypeError('connectString is required.');
|
||||
}
|
||||
|
||||
if (typeof opts.directory === 'undefined') {
|
||||
throw new TypeError('directory is a required argument.');
|
||||
}
|
||||
|
||||
if (typeof opts.appID === 'undefined') {
|
||||
throw new TypeError('appID is a required argument.');
|
||||
}
|
||||
|
||||
if (opts.destination.toLowerCase() === 'plugin' && typeof opts.pluginName === 'undefined') {
|
||||
throw new Error('pluginName is a required argument.');
|
||||
}
|
||||
|
||||
if (!fs.existsSync(opts.directory)) {
|
||||
throw new Error(`Directory ${opts.directory} is not a valid path.`);
|
||||
}
|
||||
|
||||
const getAllFiles = dir =>
|
||||
fs.readdirSync(dir).reduce((files, file) => {
|
||||
const name = path.join(dir, file);
|
||||
const isDirectory = fs.statSync(name).isDirectory();
|
||||
return isDirectory ? [...files, ...getAllFiles(name)] : [...files, name];
|
||||
}, []);
|
||||
|
||||
if (getAllFiles(opts.directory).length === 0) {
|
||||
console.log(`Directory is empty.`);
|
||||
} else {
|
||||
// Execute the upload process
|
||||
try {
|
||||
switch (opts.destination.toLowerCase()) {
|
||||
case 'theme':
|
||||
console.log(`Uploading to ${opts.appID} - Theme Files...`);
|
||||
break;
|
||||
case 'workspace':
|
||||
console.log(`Uploading to ${opts.appID} - Workspace Files...`);
|
||||
break;
|
||||
case 'plugin':
|
||||
console.log(`Uploading to ${opts.appID} - ${opts.pluginName} - Plugin Files...`);
|
||||
break;
|
||||
default:
|
||||
console.log(`Uploading to ${opts.appID} - Application Static Files...`);
|
||||
}
|
||||
|
||||
const spawnOpts = [
|
||||
opts.connectString, // Connect string (user/pass@server:port/sid)
|
||||
'@' + path.resolve(__dirname, 'lib/script'), // Sql to execute
|
||||
path.resolve(__dirname, 'lib/distUpload.js'), // Param &1 (js to execute)
|
||||
path.resolve(opts.directory), // Param &2
|
||||
opts.appID, // Param &3
|
||||
opts.destination, // Param &4
|
||||
opts.pluginName // Param &5
|
||||
];
|
||||
|
||||
const childProcess = spawnSync(
|
||||
opts.sqlclPath, // Sqlcl path
|
||||
spawnOpts, {
|
||||
encoding: 'utf8'
|
||||
}
|
||||
);
|
||||
|
||||
console.log(childProcess.stdout);
|
||||
console.log('Files were uploaded successfully.');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
// Provenance: vincentmorneau/apex-publish-static-files (vuln).
|
||||
// repo: vincentmorneau/apex-publish-static-files
|
||||
// commit: 8d28fe8a9a49e5ff3f61e239293b5646528e2915
|
||||
// parent: 8d28fe8a9a49e5ff3f61e239293b5646528e2915
|
||||
// commit_url: https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063
|
||||
// cve: CVE-2018-16462
|
||||
// license: MIT
|
||||
// function: publish
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 7
|
||||
|
||||
module.exports = {
|
||||
// Validates a JSON object
|
||||
publish(opts) {
|
||||
// Set defaults
|
||||
const defaults = {
|
||||
sqlclPath: 'sql',
|
||||
destination: 'application'
|
||||
};
|
||||
opts = Object.assign(defaults, opts);
|
||||
|
||||
// Validate arguments
|
||||
if (typeof opts.connectString === 'undefined') {
|
||||
throw new TypeError('connectString is required.');
|
||||
}
|
||||
|
||||
if (typeof opts.directory === 'undefined') {
|
||||
throw new TypeError('directory is a required argument.');
|
||||
}
|
||||
|
||||
if (typeof opts.appID === 'undefined') {
|
||||
throw new TypeError('appID is a required argument.');
|
||||
}
|
||||
|
||||
if (opts.destination.toLowerCase() === 'plugin' && typeof opts.pluginName === 'undefined') {
|
||||
throw new Error('pluginName is a required argument.');
|
||||
}
|
||||
|
||||
if (!fs.existsSync(opts.directory)) {
|
||||
throw new Error(`Directory ${opts.directory} is not a valid path.`);
|
||||
}
|
||||
|
||||
// Execute the upload process
|
||||
try {
|
||||
switch (opts.destination.toLowerCase()) {
|
||||
case 'theme':
|
||||
console.log(`Uploading to ${opts.appID} - Theme Files...`);
|
||||
break;
|
||||
case 'workspace':
|
||||
console.log(`Uploading to ${opts.appID} - Workspace Files...`);
|
||||
break;
|
||||
case 'plugin':
|
||||
console.log(`Uploading to ${opts.appID} - ${opts.pluginName} - Plugin Files...`);
|
||||
break;
|
||||
default:
|
||||
console.log(`Uploading to ${opts.appID} - Application Static Files...`);
|
||||
}
|
||||
|
||||
const childProcess = execSync(
|
||||
'"' + opts.sqlclPath + '"' + // Sqlcl path
|
||||
' ' + opts.connectString + // Connect string (user/pass@server:port/sid)
|
||||
' @"' + path.resolve(__dirname, 'lib/script') + '"' + // Sql to execute
|
||||
' "' + path.resolve(__dirname, 'lib/distUpload.js') + '"' + // Param &1 (js to execute)
|
||||
' "' + path.resolve(opts.directory) + '"' + // Param &2
|
||||
' ' + opts.appID + // Param &3
|
||||
' "' + opts.destination + '"' + // Param &4
|
||||
' "' + opts.pluginName + '"' // Param &5
|
||||
, {
|
||||
encoding: 'utf8'
|
||||
}
|
||||
);
|
||||
|
||||
console.log(childProcess);
|
||||
|
||||
console.log('Files were uploaded successfully.');
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
// Provenance: nfriedly/node-bestzip (fixed).
|
||||
// repo: nfriedly/node-bestzip
|
||||
// commit: 45d4a901478c6a8f396c8b959dd6cf8fd3f955b6
|
||||
// parent: fcea252e52b6078eff6caf5531bd32c53fccb59f
|
||||
// commit_url: https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6
|
||||
// cve: CVE-2020-7730
|
||||
// license: MIT
|
||||
// function: nativeZip
|
||||
// relpath: lib/bestzip.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 66
|
||||
|
||||
const nativeZip = options =>
|
||||
new Promise((resolve, reject) => {
|
||||
const cwd = options.cwd || process.cwd();
|
||||
const command = "zip";
|
||||
expandSources(cwd, options.source, (err, sources) => {
|
||||
const args = ["--quiet", "--recurse-paths", options.destination].concat(
|
||||
sources
|
||||
);
|
||||
const zipProcess = cp.spawn(command, args, {
|
||||
stdio: "inherit",
|
||||
cwd
|
||||
});
|
||||
zipProcess.on("error", reject);
|
||||
zipProcess.on("close", exitCode => {
|
||||
if (exitCode === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
// exit code 12 means "nothing to do" right?
|
||||
//console.log('rejecting', zipProcess)
|
||||
reject(
|
||||
new Error(
|
||||
`Unexpected exit code from native zip: ${exitCode}\n executed command '${command} ${args.join(
|
||||
" "
|
||||
)}'\n executed in directory '${cwd}'`
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
// Provenance: nfriedly/node-bestzip (vuln).
|
||||
// repo: nfriedly/node-bestzip
|
||||
// commit: fcea252e52b6078eff6caf5531bd32c53fccb59f
|
||||
// parent: fcea252e52b6078eff6caf5531bd32c53fccb59f
|
||||
// commit_url: https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6
|
||||
// cve: CVE-2020-7730
|
||||
// license: MIT
|
||||
// function: nativeZip
|
||||
// relpath: lib/bestzip.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 66
|
||||
|
||||
const nativeZip = options =>
|
||||
new Promise((resolve, reject) => {
|
||||
const sources = Array.isArray(options.source)
|
||||
? options.source.join(" ")
|
||||
: options.source;
|
||||
const command = `zip --quiet --recurse-paths ${
|
||||
options.destination
|
||||
} ${sources}`;
|
||||
const zipProcess = cp.exec(command, {
|
||||
stdio: "inherit",
|
||||
cwd: options.cwd
|
||||
});
|
||||
zipProcess.on("error", reject);
|
||||
zipProcess.on("close", exitCode => {
|
||||
if (exitCode === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
// exit code 12 means "nothing to do" right?
|
||||
//console.log('rejecting', zipProcess)
|
||||
reject(
|
||||
new Error(
|
||||
`Unexpected exit code from native zip command: ${exitCode}\n executed command '${command}'\n executed inin directory '${options.cwd ||
|
||||
process.cwd()}'`
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,188 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build vfc-js recipes from SecBench.js fix commits (maintainer, network via gh).
|
||||
|
||||
SecBench.js has no license file, so nothing from it is vendored. Its package.json
|
||||
metadata names the upstream fix commit; the pair is harvested from that upstream
|
||||
repository (hunk mode: the function enclosing the first changed hunk) and carries
|
||||
the upstream package license. Crawl first:
|
||||
|
||||
python benchmarks/pairs/vfc-js/build_recipes.py --crawl /tmp/secbench.jsonl # lists modules with a GitHub fixCommit
|
||||
python benchmarks/pairs/vfc-js/build_recipes.py --from /tmp/secbench.jsonl # resolves parent, license, changed file
|
||||
python benchmarks/pairs/harvest.py --slice vfc-js --all --fetch
|
||||
python benchmarks/pairs/catalog_gen.py --slice vfc-js
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
CLASSES = {
|
||||
"command-injection": ("CWE-78", "command injection", "source_reaches_sink"),
|
||||
"path-traversal": ("CWE-22", "path traversal", "path_join_user_input"),
|
||||
"code-injection": ("CWE-94", "code injection", "source_reaches_sink"),
|
||||
"prototype-pollution": ("CWE-1321", "prototype pollution", "prototype_pollution"),
|
||||
"redos": ("CWE-1333", "regular expression denial of service", "redos"),
|
||||
}
|
||||
ACCEPTED_LICENSES = {"MIT", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "ISC", "MPL-2.0", "GPL-3.0", "GPL-2.0", "Unlicense", "0BSD"}
|
||||
_JS = re.compile(r"\.(js|mjs|cjs|ts)$")
|
||||
_SKIP = re.compile(r"(test|spec|\.d\.ts|dist/|build/|min\.js|package\.json|README)", re.I)
|
||||
|
||||
|
||||
def _gh(path: str) -> object:
|
||||
return json.loads(subprocess.check_output(["gh", "api", path], stderr=subprocess.DEVNULL))
|
||||
|
||||
|
||||
def crawl(out: Path, classes: tuple[str, ...]) -> int:
|
||||
count = 0
|
||||
with out.open("w") as handle:
|
||||
for cls in classes:
|
||||
dirs = _gh(f"repos/cristianstaicu/SecBench.js/contents/{cls}")
|
||||
for entry in dirs if isinstance(dirs, list) else []:
|
||||
if entry.get("type") != "dir":
|
||||
continue
|
||||
time.sleep(0.4)
|
||||
try:
|
||||
raw = subprocess.check_output(
|
||||
["gh", "api", f"repos/cristianstaicu/SecBench.js/contents/{cls}/{entry['name']}/package.json", "--jq", ".content"],
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
meta = json.loads(base64.b64decode(raw))
|
||||
except Exception: # noqa: BLE001 — skip unreadable modules
|
||||
continue
|
||||
fix = str(meta.get("fixCommit", "n/a"))
|
||||
if "github.com" in fix and "/commit/" in fix:
|
||||
handle.write(
|
||||
json.dumps(
|
||||
{"class": cls, "module": entry["name"], "cve": meta.get("id"), "fixCommit": fix, "sink": meta.get("sink")}
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
def build(crawl_path: Path, *, limit: int) -> tuple[list[dict[str, object]], dict[str, int]]:
|
||||
recipes: list[dict[str, object]] = []
|
||||
skipped = {"unlicensed": 0, "no_js_file": 0, "api": 0, "multi_file": 0}
|
||||
rows = [json.loads(line) for line in crawl_path.read_text().splitlines() if line.strip()]
|
||||
seen_shas: set[str] = set()
|
||||
seen_modules: set[str] = set()
|
||||
skipped.update({"duplicate_fix": 0, "module_repo_mismatch": 0})
|
||||
for row in rows:
|
||||
if len(recipes) >= limit:
|
||||
break
|
||||
match = re.search(r"github\.com/([^/]+/[^/]+)/commit/([0-9a-f]{7,40})", row["fixCommit"])
|
||||
if not match:
|
||||
continue
|
||||
repo, sha = match.group(1), match.group(2)
|
||||
module_base = re.sub(r"[^a-z0-9]", "", str(row["module"]).rsplit("_", 1)[0].lower())
|
||||
repo_base = re.sub(r"[^a-z0-9]", "", repo.split("/")[-1].lower())
|
||||
if sha[:10] in seen_shas or str(row["module"]) in seen_modules:
|
||||
skipped["duplicate_fix"] += 1 # SecBench.js records one upstream fix under several module names
|
||||
continue
|
||||
if module_base not in repo_base and repo_base not in module_base:
|
||||
skipped["module_repo_mismatch"] += 1 # the fix commit belongs to another package; do not attribute
|
||||
continue
|
||||
seen_shas.add(sha[:10])
|
||||
seen_modules.add(str(row["module"]))
|
||||
time.sleep(0.6)
|
||||
try:
|
||||
commit = _gh(f"repos/{repo}/commits/{sha}")
|
||||
info = _gh(f"repos/{repo}")
|
||||
except Exception: # noqa: BLE001 — upstream gone or renamed
|
||||
skipped["api"] += 1
|
||||
continue
|
||||
assert isinstance(commit, dict) and isinstance(info, dict)
|
||||
license_id = (info.get("license") or {}).get("spdx_id") or ""
|
||||
if license_id not in ACCEPTED_LICENSES:
|
||||
skipped["unlicensed"] += 1
|
||||
continue
|
||||
files = [f for f in commit.get("files", []) if _JS.search(f["filename"]) and not _SKIP.search(f["filename"]) and f.get("patch")]
|
||||
if not files:
|
||||
skipped["no_js_file"] += 1
|
||||
continue
|
||||
if len(files) > 3:
|
||||
skipped["multi_file"] += 1
|
||||
continue
|
||||
target = sorted(files, key=lambda f: -(f.get("additions", 0) + f.get("deletions", 0)))[0]
|
||||
parents = commit.get("parents") or []
|
||||
if not parents:
|
||||
skipped["api"] += 1
|
||||
continue
|
||||
cwe, cls_text, mechanism = CLASSES[row["class"]]
|
||||
module = str(row["module"])
|
||||
name = f"{re.sub(r'[^a-z0-9]+', '-', module.lower()).strip('-')}"[:60]
|
||||
recipes.append(
|
||||
{
|
||||
"name": name,
|
||||
"host": "github",
|
||||
"repo": repo,
|
||||
"parent": parents[0]["sha"],
|
||||
"commit": commit["sha"],
|
||||
"path": target["filename"],
|
||||
"mode": "hunk",
|
||||
"language": "typescript" if target["filename"].endswith(".ts") else "javascript",
|
||||
"relpath": target["filename"],
|
||||
"license": license_id,
|
||||
"cve": str(row.get("cve") or ""),
|
||||
"year": int(str(commit["commit"]["author"]["date"])[:4]),
|
||||
"cwe": cwe,
|
||||
"class": cls_text,
|
||||
"mechanism": mechanism,
|
||||
"provenance": "human",
|
||||
"origin": "secbench.js",
|
||||
"project": module.rsplit("_", 1)[0],
|
||||
"sink_location": str(row.get("sink") or ""),
|
||||
"secbench_class": row["class"],
|
||||
"evidence": f"SecBench.js {row['class']} sink {row.get('sink')} fixed upstream in {sha[:12]}",
|
||||
"commit_url": f"https://github.com/{repo}/commit/{commit['sha']}",
|
||||
}
|
||||
)
|
||||
for index, recipe in enumerate(sorted(recipes, key=lambda r: str(r["name"]))):
|
||||
recipe["split"] = "holdout" if index % 2 else "train"
|
||||
return recipes, skipped
|
||||
|
||||
|
||||
def to_toml(recipes: list[dict[str, object]]) -> str:
|
||||
lines = [
|
||||
"# vfc-js harvest recipes derived from SecBench.js fixCommit metadata by build_recipes.py.",
|
||||
"# Excerpts come from the upstream package repository (its license), never from SecBench.js.",
|
||||
"",
|
||||
]
|
||||
for recipe in sorted(recipes, key=lambda r: str(r["name"])):
|
||||
lines.append("[[recipe]]")
|
||||
for key, value in recipe.items():
|
||||
if isinstance(value, int) and not isinstance(value, bool):
|
||||
lines.append(f"{key} = {value}")
|
||||
else:
|
||||
lines.append(f'{key} = "{str(value).replace(chr(92), chr(92) * 2).replace(chr(34), chr(92) + chr(34))}"')
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--crawl", type=Path, help="write the SecBench.js module list with GitHub fix commits to this jsonl")
|
||||
parser.add_argument("--classes", default="command-injection,path-traversal,code-injection")
|
||||
parser.add_argument("--from", dest="source", type=Path, help="jsonl produced by --crawl")
|
||||
parser.add_argument("--limit", type=int, default=40)
|
||||
parser.add_argument("--out", type=Path, default=ROOT / "recipes.toml")
|
||||
args = parser.parse_args(argv)
|
||||
if args.crawl:
|
||||
print(f"crawled {crawl(args.crawl, tuple(args.classes.split(',')))} modules -> {args.crawl}")
|
||||
if args.source:
|
||||
recipes, skipped = build(args.source, limit=args.limit)
|
||||
args.out.write_text(to_toml(recipes), encoding="utf-8")
|
||||
print(f"wrote {args.out} ({len(recipes)} recipes); skipped {skipped}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,493 @@
|
||||
# vfc-js pair slice. Reviewed isolated functions with provenance.
|
||||
# Honesty dashboard — not the local 100% CI gate.
|
||||
# Do not add these names to LANGUAGE_MANIFESTS.
|
||||
# Regenerated by benchmarks/pairs/catalog_gen.py from recipes.toml.
|
||||
|
||||
[[pair]]
|
||||
name = "angular-http-server-1-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "Apache-2.0"
|
||||
repo = "simonh1000/angular-http-server"
|
||||
cve = ""
|
||||
cwe = "CWE-22"
|
||||
commit = "8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
parent = "d171a771a92e4685b24fb77cb894a7b7b8024c5c"
|
||||
commit_url = "https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
vuln = "angular-http-server-1-0-0/vuln.js"
|
||||
fixed = "angular-http-server-1-0-0/fixed.js"
|
||||
relpath = "angular-http-server.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "angular-http-server.js"
|
||||
function = "requestListener"
|
||||
mechanism = "path_join_user_input"
|
||||
sink = "path"
|
||||
evidence = "SecBench.js path-traversal sink angular-http-server.js:16:29 fixed upstream in 8bafc9577161"
|
||||
|
||||
[[pair]]
|
||||
name = "apex-publish-static-files-2-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "vincentmorneau/apex-publish-static-files"
|
||||
cve = "CVE-2018-16462"
|
||||
cwe = "CWE-78"
|
||||
commit = "2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
parent = "8d28fe8a9a49e5ff3f61e239293b5646528e2915"
|
||||
commit_url = "https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
vuln = "apex-publish-static-files-2-0-0/vuln.js"
|
||||
fixed = "apex-publish-static-files-2-0-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "publish"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:54:25 fixed upstream in 2209af8f2b65"
|
||||
|
||||
[[pair]]
|
||||
name = "bestzip-2-1-6"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "nfriedly/node-bestzip"
|
||||
cve = "CVE-2020-7730"
|
||||
cwe = "CWE-78"
|
||||
commit = "45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
parent = "fcea252e52b6078eff6caf5531bd32c53fccb59f"
|
||||
commit_url = "https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
vuln = "bestzip-2-1-6/vuln.js"
|
||||
fixed = "bestzip-2-1-6/fixed.js"
|
||||
relpath = "lib/bestzip.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/bestzip.js"
|
||||
function = "nativeZip"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/bestzip.js:27:27 fixed upstream in 45d4a901478c"
|
||||
|
||||
[[pair]]
|
||||
name = "clamscan-1-2-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "kylefarris/clamscan"
|
||||
cve = "CVE-2020-7613"
|
||||
cwe = "CWE-78"
|
||||
commit = "5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
parent = "d474da7b89c0d3397cd681e79c7bcc592bff144b"
|
||||
commit_url = "https://github.com/kylefarris/clamscan/commit/5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
vuln = "clamscan-1-2-0/vuln.js"
|
||||
fixed = "clamscan-1-2-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "local_scan"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:495:36 fixed upstream in 5f557c970817"
|
||||
|
||||
[[pair]]
|
||||
name = "diskusage-ng-0-2-6"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "iximiuz/node-diskusage-ng"
|
||||
cve = "CVE-2020-7631"
|
||||
cwe = "CWE-78"
|
||||
commit = "48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
parent = "53c505506553c83861d1bd67823d6a382d3a5a43"
|
||||
commit_url = "https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
vuln = "diskusage-ng-0-2-6/vuln.js"
|
||||
fixed = "diskusage-ng-0-2-6/fixed.js"
|
||||
relpath = "lib/posix.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/posix.js"
|
||||
function = "diskusage"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/posix.js:11:5 fixed upstream in 48e7e093486b"
|
||||
|
||||
[[pair]]
|
||||
name = "dns-sync-0-1-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "skoranga/node-dns-sync"
|
||||
cve = "CVE-2014-9682"
|
||||
cwe = "CWE-78"
|
||||
commit = "d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
parent = "b748fe77a87749d95876028eda8e759109be4c73"
|
||||
commit_url = "https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
vuln = "dns-sync-0-1-0/vuln.js"
|
||||
fixed = "dns-sync-0-1-0/fixed.js"
|
||||
relpath = "lib/dns-sync.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/dns-sync.js"
|
||||
function = "resolve"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/dns-sync.js:21:26 fixed upstream in d9abaae384b1"
|
||||
|
||||
[[pair]]
|
||||
name = "glance-3-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "jarofghosts/glance"
|
||||
cve = "CVE-2018-3715"
|
||||
cwe = "CWE-22"
|
||||
commit = "8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
parent = "7e69a5539236386e747fb240ae87ea65ed64bb2c"
|
||||
commit_url = "https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
vuln = "glance-3-0-0/vuln.js"
|
||||
fixed = "glance-3-0-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "index.js"
|
||||
function = "Glance$serveRequest"
|
||||
mechanism = "path_join_user_input"
|
||||
evidence = "SecBench.js path-traversal sink index.js:81:14 fixed upstream in 8cfd88e44ebd"
|
||||
|
||||
[[pair]]
|
||||
name = "hot-formula-parser-3-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "handsontable/formula-parser"
|
||||
cve = "CVE-2020-6836"
|
||||
cwe = "CWE-78"
|
||||
commit = "396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
parent = "944136096f44ff4ffd4ba0bcef30970ca4702fce"
|
||||
commit_url = "https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
vuln = "hot-formula-parser-3-0-0/vuln.js"
|
||||
fixed = "hot-formula-parser-3-0-0/fixed.js"
|
||||
relpath = "src/grammar-parser/grammar-parser.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "src/grammar-parser/grammar-parser.js"
|
||||
function = "performAction"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "SecBench.js command-injection sink lib/grammar-parser/grammar-parser.js:258:31 fixed upstream in 396b089738d4"
|
||||
|
||||
[[pair]]
|
||||
name = "libnmap-0-4-11"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "jas-/node-libnmap"
|
||||
cve = "CVE-2018-16461"
|
||||
cwe = "CWE-78"
|
||||
commit = "c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
parent = "49b72239b144ab7ffdf673b62e18bfd0760948f6"
|
||||
commit_url = "https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
vuln = "libnmap-0-4-11/vuln.js"
|
||||
fixed = "libnmap-0-4-11/fixed.js"
|
||||
relpath = "lib/classes/tools.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/classes/tools.js"
|
||||
function = "block"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "SecBench.js command-injection sink lib/classes/tools.js:114:25 fixed upstream in c235b24b0342"
|
||||
|
||||
[[pair]]
|
||||
name = "pdf-image-1-0-5"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "roest01/node-pdf-image"
|
||||
cve = "CVE-2018-3757"
|
||||
cwe = "CWE-78"
|
||||
commit = "54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
parent = "d8c0dcadd93985dbefe80b84060f5f572bfbb6ff"
|
||||
commit_url = "https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
vuln = "pdf-image-1-0-5/vuln.js"
|
||||
fixed = "pdf-image-1-0-5/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "getInfo"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:43:7 fixed upstream in 54679496a897"
|
||||
|
||||
[[pair]]
|
||||
name = "pidusage-1-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "soyuka/pidusage"
|
||||
cve = "CVE-2017-16034"
|
||||
cwe = "CWE-78"
|
||||
commit = "b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
parent = "e3660d8a8e5e61afad9b02af67356a1e239d6bde"
|
||||
commit_url = "https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
vuln = "pidusage-1-0-0/vuln.js"
|
||||
fixed = "pidusage-1-0-0/fixed.js"
|
||||
relpath = "lib/stats.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/stats.js"
|
||||
function = "ps"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/stats.js:108:5 fixed upstream in b70eca15f7ca"
|
||||
|
||||
[[pair]]
|
||||
name = "portprocesses-1-0-4"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "rrainn/PortProcesses"
|
||||
cve = "CVE-2021-23348"
|
||||
cwe = "CWE-78"
|
||||
commit = "86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
parent = "fffceb09aff7180afbd0bd172e820404b33c8299"
|
||||
commit_url = "https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
vuln = "portprocesses-1-0-4/vuln.js"
|
||||
fixed = "portprocesses-1-0-4/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "listProcessesOnPort"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink exec.js:5:3 fixed upstream in 86811216c9b9"
|
||||
|
||||
[[pair]]
|
||||
name = "serve-here-js-1-1-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "ChristoPy/serve-here.js"
|
||||
cve = "CVE-2019-5444"
|
||||
cwe = "CWE-22"
|
||||
commit = "cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
parent = "ad077637bf7a9fe0dee3262f011aed19a45ce92c"
|
||||
commit_url = "https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
vuln = "serve-here-js-1-1-0/vuln.js"
|
||||
fixed = "serve-here-js-1-1-0/fixed.js"
|
||||
relpath = "source/response.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "source/response.js"
|
||||
function = "ConfigureFilePath"
|
||||
mechanism = "path_join_user_input"
|
||||
evidence = "SecBench.js path-traversal sink source/server.js:27:15 fixed upstream in cefb51d03290"
|
||||
|
||||
[[pair]]
|
||||
name = "static-eval-1-1-1"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "browserify/static-eval"
|
||||
cve = ""
|
||||
cwe = "CWE-94"
|
||||
commit = "32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
parent = "5bba7905b0e797460b8f6c2e38ff6869146faab3"
|
||||
commit_url = "https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
vuln = "static-eval-1-1-1/vuln.js"
|
||||
fixed = "static-eval-1-1-1/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
path = "index.js"
|
||||
function = "walk"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "eval"
|
||||
evidence = "SecBench.js code-injection sink index.js:118:20 fixed upstream in 32f8efd07262"
|
||||
|
||||
[[pair]]
|
||||
name = "thenify-3-3-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "thenables/thenify"
|
||||
cve = "CVE-2020-7677"
|
||||
cwe = "CWE-94"
|
||||
commit = "0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
parent = "aa21cfb64f47238c764d258d0faf7366a8487e36"
|
||||
commit_url = "https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
vuln = "thenify-3-3-0/vuln.js"
|
||||
fixed = "thenify-3-3-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
path = "index.js"
|
||||
function = "thenify"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "eval"
|
||||
evidence = "SecBench.js code-injection sink index.js:17:10 fixed upstream in 0d94a24eb933"
|
||||
|
||||
[[pair]]
|
||||
name = "underscore-1-13-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "jashkenas/underscore"
|
||||
cve = "CVE-2021-23358"
|
||||
cwe = "CWE-94"
|
||||
commit = "4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
parent = "ef646ccbbbd971e82719c83fc69f56a5585b3a01"
|
||||
commit_url = "https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
vuln = "underscore-1-13-0-0/vuln.js"
|
||||
fixed = "underscore-1-13-0-0/fixed.js"
|
||||
relpath = "modules/template.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
path = "modules/template.js"
|
||||
function = "template"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "eval"
|
||||
evidence = "SecBench.js code-injection sink modules/template.js:71:14 fixed upstream in 4c73526d4383"
|
||||
|
||||
[[pair]]
|
||||
name = "whereis-0-4-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "vvo/node-whereis"
|
||||
cve = "CVE-2018-3772"
|
||||
cwe = "CWE-78"
|
||||
commit = "0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
parent = "b8b642b1163baa37f15ed49b4064dcbdb6e1876c"
|
||||
commit_url = "https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
vuln = "whereis-0-4-0/vuln.js"
|
||||
fixed = "whereis-0-4-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "whereis"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:4:6 fixed upstream in 0f64e3780235"
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
// Provenance: iximiuz/node-diskusage-ng (fixed).
|
||||
// repo: iximiuz/node-diskusage-ng
|
||||
// commit: 48e7e093486b528f0c81ec699573e0e4a431b8d3
|
||||
// parent: 53c505506553c83861d1bd67823d6a382d3a5a43
|
||||
// commit_url: https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3
|
||||
// cve: CVE-2020-7631
|
||||
// license: MIT
|
||||
// function: diskusage
|
||||
// relpath: lib/posix.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 6
|
||||
|
||||
function diskusage(path, cb) {
|
||||
execFile('df', ['-k', path], function(err, stdout) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
try {
|
||||
cb(null, parse(stdout));
|
||||
} catch (e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Provenance: iximiuz/node-diskusage-ng (vuln).
|
||||
// repo: iximiuz/node-diskusage-ng
|
||||
// commit: 53c505506553c83861d1bd67823d6a382d3a5a43
|
||||
// parent: 53c505506553c83861d1bd67823d6a382d3a5a43
|
||||
// commit_url: https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3
|
||||
// cve: CVE-2020-7631
|
||||
// license: MIT
|
||||
// function: diskusage
|
||||
// relpath: lib/posix.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 6
|
||||
|
||||
function diskusage(path, cb) {
|
||||
if (path.indexOf('"') !== -1) {
|
||||
return cb(new Error('Paths with double quotes are not supported yet'));
|
||||
}
|
||||
|
||||
exec('df -k "' + path + '"', function(err, stdout) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
try {
|
||||
cb(null, parse(stdout));
|
||||
} catch (e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Provenance: skoranga/node-dns-sync (fixed).
|
||||
// repo: skoranga/node-dns-sync
|
||||
// commit: d9abaae384b198db1095735ad9c1c73d7b890a0d
|
||||
// parent: b748fe77a87749d95876028eda8e759109be4c73
|
||||
// commit_url: https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d
|
||||
// cve: CVE-2014-9682
|
||||
// license: MIT
|
||||
// function: resolve
|
||||
// relpath: lib/dns-sync.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 19
|
||||
|
||||
module.exports = {
|
||||
resolve: function resolve(hostname) {
|
||||
var output,
|
||||
nodeBinary = process.execPath;
|
||||
|
||||
if (!isValidHostName(hostname)) {
|
||||
console.error('Invalid hostname:', hostname);
|
||||
return null;
|
||||
}
|
||||
|
||||
var scriptPath = path.join(__dirname, "../scripts/dns-lookup-script"),
|
||||
response,
|
||||
cmd = util.format('"%s" "%s" %s', nodeBinary, scriptPath, hostname);
|
||||
|
||||
response = shell.exec(cmd, {silent: true});
|
||||
if (response && response.code === 0) {
|
||||
output = response.output;
|
||||
if (output && net.isIP(output)) {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
debug('hostname', "fail to resolve hostname " + hostname);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// Provenance: skoranga/node-dns-sync (vuln).
|
||||
// repo: skoranga/node-dns-sync
|
||||
// commit: b748fe77a87749d95876028eda8e759109be4c73
|
||||
// parent: b748fe77a87749d95876028eda8e759109be4c73
|
||||
// commit_url: https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d
|
||||
// cve: CVE-2014-9682
|
||||
// license: MIT
|
||||
// function: resolve
|
||||
// relpath: lib/dns-sync.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 13
|
||||
|
||||
module.exports = {
|
||||
resolve: function resolve(hostname) {
|
||||
var output,
|
||||
nodeBinary = process.execPath,
|
||||
scriptPath = path.join(__dirname, "../scripts/dns-lookup-script"),
|
||||
response,
|
||||
cmd = util.format('"%s" "%s" %s', nodeBinary, scriptPath, hostname);
|
||||
|
||||
response = shell.exec(cmd, {silent: true});
|
||||
if (response && response.code === 0) {
|
||||
output = response.output;
|
||||
if (output && net.isIP(output)) {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
debug('hostname', "fail to resolve hostname " + hostname);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
// Provenance: jarofghosts/glance (fixed).
|
||||
// repo: jarofghosts/glance
|
||||
// commit: 8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19
|
||||
// parent: 7e69a5539236386e747fb240ae87ea65ed64bb2c
|
||||
// commit_url: https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19
|
||||
// cve: CVE-2018-3715
|
||||
// license: MIT
|
||||
// function: Glance$serveRequest
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 60
|
||||
|
||||
Glance.prototype.serveRequest = function Glance$serveRequest (req, res) {
|
||||
var request = {}
|
||||
var self = this
|
||||
|
||||
request.fullPath = path.join(
|
||||
self.dir,
|
||||
decodeURIComponent(parse(req.url).pathname)
|
||||
)
|
||||
|
||||
request.ip = req.socket.remoteAddress
|
||||
request.method = req.method.toLowerCase()
|
||||
request.response = res
|
||||
|
||||
// prevent traversing directories that are parents of the root
|
||||
if (request.fullPath.slice(0, self.dir.length) !== self.dir) {
|
||||
return self.emit('error', 403, request, res)
|
||||
}
|
||||
|
||||
if (request.method !== 'get') {
|
||||
return self.emit('error', 405, request, res)
|
||||
}
|
||||
|
||||
if (self.nodot && /^\./.test(path.basename(request.fullPath))) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
fs.stat(request.fullPath, statFile)
|
||||
|
||||
function statFile (err, stat) {
|
||||
if (err) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
self.emit('read', request)
|
||||
|
||||
return filed(request.fullPath).pipe(res)
|
||||
}
|
||||
|
||||
if (self.hideindex) {
|
||||
return self.emit('error', 403, request, res)
|
||||
}
|
||||
|
||||
if (!self.indices || !self.indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
var indices = self.indices.slice()
|
||||
|
||||
findIndex(indices.shift())
|
||||
|
||||
function findIndex (indexTest) {
|
||||
fileExists(path.join(request.fullPath, indexTest), check)
|
||||
|
||||
function check (hasIndex) {
|
||||
if (hasIndex) {
|
||||
req.url = req.url + '/' + indexTest
|
||||
|
||||
return self.serveRequest(req, res)
|
||||
}
|
||||
|
||||
if (!indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
findIndex(indices.shift())
|
||||
}
|
||||
}
|
||||
|
||||
function listFiles () {
|
||||
var listPath = request.fullPath.replace(/\/$/, '')
|
||||
|
||||
res.writeHead(200, RESPONSE_HEADERS)
|
||||
htmlls(listPath, {hideDot: self.nodot}).pipe(res)
|
||||
|
||||
return self.emit('read', request)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Provenance: jarofghosts/glance (vuln).
|
||||
// repo: jarofghosts/glance
|
||||
// commit: 7e69a5539236386e747fb240ae87ea65ed64bb2c
|
||||
// parent: 7e69a5539236386e747fb240ae87ea65ed64bb2c
|
||||
// commit_url: https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19
|
||||
// cve: CVE-2018-3715
|
||||
// license: MIT
|
||||
// function: Glance$serveRequest
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 60
|
||||
|
||||
Glance.prototype.serveRequest = function Glance$serveRequest (req, res) {
|
||||
var request = {}
|
||||
var self = this
|
||||
|
||||
request.fullPath = path.join(
|
||||
self.dir,
|
||||
decodeURIComponent(parse(req.url).pathname)
|
||||
)
|
||||
|
||||
request.ip = req.socket.remoteAddress
|
||||
request.method = req.method.toLowerCase()
|
||||
request.response = res
|
||||
|
||||
if (request.method !== 'get') {
|
||||
return self.emit('error', 405, request, res)
|
||||
}
|
||||
|
||||
if (self.nodot && /^\./.test(path.basename(request.fullPath))) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
fs.stat(request.fullPath, statFile)
|
||||
|
||||
function statFile (err, stat) {
|
||||
if (err) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
self.emit('read', request)
|
||||
|
||||
return filed(request.fullPath).pipe(res)
|
||||
}
|
||||
|
||||
if (self.hideindex) {
|
||||
return self.emit('error', 403, request, res)
|
||||
}
|
||||
|
||||
if (!self.indices || !self.indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
var indices = self.indices.slice()
|
||||
|
||||
findIndex(indices.shift())
|
||||
|
||||
function findIndex (indexTest) {
|
||||
fileExists(path.join(request.fullPath, indexTest), check)
|
||||
|
||||
function check (hasIndex) {
|
||||
if (hasIndex) {
|
||||
req.url = req.url + '/' + indexTest
|
||||
|
||||
return self.serveRequest(req, res)
|
||||
}
|
||||
|
||||
if (!indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
findIndex(indices.shift())
|
||||
}
|
||||
}
|
||||
|
||||
function listFiles () {
|
||||
var listPath = request.fullPath.replace(/\/$/, '')
|
||||
|
||||
res.writeHead(200, RESPONSE_HEADERS)
|
||||
htmlls(listPath, {hideDot: self.nodot}).pipe(res)
|
||||
|
||||
return self.emit('read', request)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,867 @@
|
||||
// Provenance: handsontable/formula-parser (fixed).
|
||||
// repo: handsontable/formula-parser
|
||||
// commit: 396b089738d4bf30eb570a4fe6a188affa95cd5e
|
||||
// parent: 944136096f44ff4ffd4ba0bcef30970ca4702fce
|
||||
// commit_url: https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e
|
||||
// cve: CVE-2020-6836
|
||||
// license: MIT
|
||||
// function: performAction
|
||||
// relpath: src/grammar-parser/grammar-parser.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 74
|
||||
|
||||
var grammarParser = (function(){
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,8],$V2=[1,6],$V3=[1,7],$V4=[1,9],$V5=[1,14],$V6=[1,15],$V7=[1,16],$V8=[1,12],$V9=[1,13],$Va=[1,17],$Vb=[1,19],$Vc=[1,20],$Vd=[1,21],$Ve=[1,22],$Vf=[1,23],$Vg=[1,24],$Vh=[1,25],$Vi=[1,26],$Vj=[1,27],$Vk=[1,28],$Vl=[5,9,10,11,13,14,15,16,17,18,19,20,29,30],$Vm=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,32],$Vn=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,34],$Vo=[5,10,11,13,14,15,16,17,29,30],$Vp=[5,10,13,14,15,16,29,30],$Vq=[5,10,11,13,14,15,16,17,18,19,29,30],$Vr=[13,29,30];
|
||||
var parser = {trace: function trace () { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"expressions":3,"expression":4,"EOF":5,"variableSequence":6,"number":7,"STRING":8,"&":9,"=":10,"+":11,"(":12,")":13,"<":14,">":15,"NOT":16,"-":17,"*":18,"/":19,"^":20,"FUNCTION":21,"expseq":22,"cell":23,"ABSOLUTE_CELL":24,"RELATIVE_CELL":25,"MIXED_CELL":26,":":27,"ARRAY":28,";":29,",":30,"VARIABLE":31,"DECIMAL":32,"NUMBER":33,"%":34,"ERROR":35,"$accept":0,"$end":1},
|
||||
terminals_: {5:"EOF",8:"STRING",9:"&",10:"=",11:"+",12:"(",13:")",14:"<",15:">",16:"NOT",17:"-",18:"*",19:"/",20:"^",21:"FUNCTION",24:"ABSOLUTE_CELL",25:"RELATIVE_CELL",26:"MIXED_CELL",27:":",28:"ARRAY",29:";",30:",",31:"VARIABLE",32:"DECIMAL",33:"NUMBER",34:"%",35:"ERROR"},
|
||||
productions_: [0,[3,2],[4,1],[4,1],[4,1],[4,3],[4,3],[4,3],[4,3],[4,4],[4,4],[4,4],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,2],[4,2],[4,3],[4,4],[4,1],[4,1],[4,2],[23,1],[23,1],[23,1],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[22,1],[22,1],[22,3],[22,3],[6,1],[6,3],[7,1],[7,3],[7,2],[2,1]],
|
||||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
switch (yystate) {
|
||||
case 1:
|
||||
|
||||
return $$[$0-1];
|
||||
|
||||
break;
|
||||
case 2:
|
||||
|
||||
this.$ = yy.callVariable($$[$0][0]);
|
||||
|
||||
break;
|
||||
case 3:
|
||||
|
||||
this.$ = yy.toNumber($$[$0]);
|
||||
|
||||
break;
|
||||
case 4:
|
||||
|
||||
this.$ = yy.trimEdges($$[$0]);
|
||||
|
||||
break;
|
||||
case 5:
|
||||
|
||||
this.$ = yy.evaluateByOperator('&', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 6:
|
||||
|
||||
this.$ = yy.evaluateByOperator('=', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 7:
|
||||
|
||||
this.$ = yy.evaluateByOperator('+', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 8:
|
||||
|
||||
this.$ = $$[$0-1];
|
||||
|
||||
break;
|
||||
case 9:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 10:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 11:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<>', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 12:
|
||||
|
||||
this.$ = yy.evaluateByOperator('NOT', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 13:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 14:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 15:
|
||||
|
||||
this.$ = yy.evaluateByOperator('-', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 16:
|
||||
|
||||
this.$ = yy.evaluateByOperator('*', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 17:
|
||||
|
||||
this.$ = yy.evaluateByOperator('/', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 18:
|
||||
|
||||
this.$ = yy.evaluateByOperator('^', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 19:
|
||||
|
||||
var n1 = yy.invertNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 20:
|
||||
|
||||
var n1 = yy.toNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 21:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-2]);
|
||||
|
||||
break;
|
||||
case 22:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-3], $$[$0-1]);
|
||||
|
||||
break;
|
||||
case 26: case 27: case 28:
|
||||
|
||||
this.$ = yy.cellValue($$[$0]);
|
||||
|
||||
break;
|
||||
case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
|
||||
|
||||
this.$ = yy.rangeValue($$[$0-2], $$[$0]);
|
||||
|
||||
break;
|
||||
case 38: case 42:
|
||||
|
||||
this.$ = [$$[$0]];
|
||||
|
||||
break;
|
||||
case 39:
|
||||
|
||||
this.$ = yy.trimEdges(yytext).split(',');
|
||||
|
||||
break;
|
||||
case 40: case 41:
|
||||
|
||||
$$[$0-2].push($$[$0]);
|
||||
this.$ = $$[$0-2];
|
||||
|
||||
break;
|
||||
case 43:
|
||||
|
||||
this.$ = (Array.isArray($$[$0-2]) ? $$[$0-2] : [$$[$0-2]]);
|
||||
this.$.push($$[$0]);
|
||||
|
||||
break;
|
||||
case 44:
|
||||
|
||||
this.$ = $$[$0];
|
||||
|
||||
break;
|
||||
case 45:
|
||||
|
||||
this.$ = ($$[$0-2] + '.' + $$[$0]) * 1;
|
||||
|
||||
break;
|
||||
case 46:
|
||||
|
||||
this.$ = $$[$0-1] * 0.01;
|
||||
|
||||
break;
|
||||
case 47:
|
||||
|
||||
this.$ = yy.throwError($$[$0]);
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
table: [{2:11,3:1,4:2,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{1:[3]},{5:[1,18],9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vl,[2,2],{32:[1,29]}),o($Vl,[2,3],{34:[1,30]}),o($Vl,[2,4]),{2:11,4:31,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:32,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:33,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{12:[1,34]},o($Vl,[2,23]),o($Vl,[2,24],{2:35,35:$Va}),o($Vm,[2,42]),o($Vn,[2,44],{32:[1,36]}),o($Vl,[2,26],{27:[1,37]}),o($Vl,[2,27],{27:[1,38]}),o($Vl,[2,28],{27:[1,39]}),o([5,9,10,11,13,14,15,16,17,18,19,20,29,30,35],[2,47]),{1:[2,1]},{2:11,4:40,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:41,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:42,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:45,6:3,7:4,8:$V0,10:[1,43],11:$V1,12:$V2,15:[1,44],17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:47,6:3,7:4,8:$V0,10:[1,46],11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:48,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:49,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:50,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:51,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:52,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{31:[1,53]},o($Vn,[2,46]),{9:$Vb,10:$Vc,11:$Vd,13:[1,54],14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vo,[2,19],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,20],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:57,6:3,7:4,8:$V0,11:$V1,12:$V2,13:[1,55],17:$V3,21:$V4,22:56,23:10,24:$V5,25:$V6,26:$V7,28:[1,58],31:$V8,33:$V9,35:$Va},o($Vl,[2,25]),{33:[1,59]},{24:[1,60],25:[1,61],26:[1,62]},{24:[1,63],25:[1,64],26:[1,65]},{24:[1,66],25:[1,67],26:[1,68]},o($Vl,[2,5]),o([5,10,13,29,30],[2,6],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,7],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:69,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:70,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,14],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:71,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,13],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o([5,10,13,16,29,30],[2,12],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,15],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vq,[2,16],{9:$Vb,20:$Vk}),o($Vq,[2,17],{9:$Vb,20:$Vk}),o([5,10,11,13,14,15,16,17,18,19,20,29,30],[2,18],{9:$Vb}),o($Vm,[2,43]),o($Vl,[2,8]),o($Vl,[2,21]),{13:[1,72],29:[1,73],30:[1,74]},o($Vr,[2,38],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,39]),o($Vn,[2,45]),o($Vl,[2,29]),o($Vl,[2,30]),o($Vl,[2,31]),o($Vl,[2,32]),o($Vl,[2,33]),o($Vl,[2,34]),o($Vl,[2,35]),o($Vl,[2,36]),o($Vl,[2,37]),o($Vp,[2,9],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,11],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,10],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vl,[2,22]),{2:11,4:75,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:76,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vr,[2,40],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,41],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk})],
|
||||
defaultActions: {18:[2,1]},
|
||||
parseError: function parseError (str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
} else {
|
||||
var error = new Error(str);
|
||||
error.hash = hash;
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
parse: function parse (input) {
|
||||
var self = this,
|
||||
stack = [0],
|
||||
tstack = [], // token stack
|
||||
vstack = [null], // semantic value stack
|
||||
lstack = [], // location stack
|
||||
table = this.table,
|
||||
yytext = '',
|
||||
yylineno = 0,
|
||||
yyleng = 0,
|
||||
recovering = 0,
|
||||
TERROR = 2,
|
||||
EOF = 1;
|
||||
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
|
||||
//this.reductionCount = this.shiftCount = 0;
|
||||
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
// copy state
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
}
|
||||
}
|
||||
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
}
|
||||
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
}
|
||||
|
||||
_token_stack:
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
// if token isn't its numeric value, convert
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
while (true) {
|
||||
// retreive state number from top of stack
|
||||
state = stack[stack.length - 1];
|
||||
|
||||
// use default actions if available
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
}
|
||||
// read action for current state and first input
|
||||
action = table[state] && table[state][symbol];
|
||||
}
|
||||
|
||||
_handle_error:
|
||||
// handle parse error
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var error_rule_depth;
|
||||
var errStr = '';
|
||||
|
||||
// Return the rule stack depth where the nearest error rule can be found.
|
||||
// Return FALSE when no error recovery rule was found.
|
||||
function locateNearestErrorRecoveryRule(state) {
|
||||
var stack_probe = stack.length - 1;
|
||||
var depth = 0;
|
||||
|
||||
// try to recover from error
|
||||
for(;;) {
|
||||
// check for error recovery rule in this state
|
||||
if ((TERROR.toString()) in table[state]) {
|
||||
return depth;
|
||||
}
|
||||
if (state === 0 || stack_probe < 2) {
|
||||
return false; // No suitable error recovery rule available.
|
||||
}
|
||||
stack_probe -= 2; // popStack(1): [symbol, action]
|
||||
state = stack[stack_probe];
|
||||
++depth;
|
||||
}
|
||||
}
|
||||
|
||||
if (!recovering) {
|
||||
// first see if there's any chance at hitting an error recovery rule:
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
|
||||
// Report error
|
||||
expected = [];
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push("'"+this.terminals_[p]+"'");
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+":\n"+lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol)+ "'";
|
||||
} else {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
|
||||
(symbol == EOF ? "end of input" :
|
||||
("'"+(this.terminals_[symbol] || symbol)+"'"));
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
token: this.terminals_[symbol] || symbol,
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected,
|
||||
recoverable: (error_rule_depth !== false)
|
||||
});
|
||||
} else if (preErrorSymbol !== EOF) {
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
}
|
||||
|
||||
// just recovered from another error
|
||||
if (recovering == 3) {
|
||||
if (symbol === EOF || preErrorSymbol === EOF) {
|
||||
throw new Error(errStr || 'Parsing halted while starting to recover from another error.');
|
||||
}
|
||||
|
||||
// discard current lookahead and grab another
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
symbol = lex();
|
||||
}
|
||||
|
||||
// try to recover from error
|
||||
if (error_rule_depth === false) {
|
||||
throw new Error(errStr || 'Parsing halted. No suitable error recovery rule available.');
|
||||
}
|
||||
popStack(error_rule_depth);
|
||||
|
||||
preErrorSymbol = (symbol == TERROR ? null : symbol); // save the lookahead token
|
||||
symbol = TERROR; // insert generic error symbol as new lookahead
|
||||
state = stack[stack.length-1];
|
||||
action = table[state] && table[state][TERROR];
|
||||
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
|
||||
}
|
||||
|
||||
// this shouldn't happen, unless resolve defaults are off
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
|
||||
}
|
||||
|
||||
switch (action[0]) {
|
||||
case 1: // shift
|
||||
//this.shiftCount++;
|
||||
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]); // push state
|
||||
symbol = null;
|
||||
if (!preErrorSymbol) { // normal execution/no error
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
}
|
||||
} else {
|
||||
// error just occurred, resume old lookahead f/ before error
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// reduce
|
||||
//this.reductionCount++;
|
||||
|
||||
len = this.productions_[action[1]][1];
|
||||
|
||||
// perform semantic action
|
||||
yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
|
||||
// default location, uses first token for firsts, last for lasts
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length-(len||1)].first_line,
|
||||
last_line: lstack[lstack.length-1].last_line,
|
||||
first_column: lstack[lstack.length-(len||1)].first_column,
|
||||
last_column: lstack[lstack.length-1].last_column
|
||||
};
|
||||
if (ranges) {
|
||||
yyval._$.range = [lstack[lstack.length-(len||1)].range[0], lstack[lstack.length-1].range[1]];
|
||||
}
|
||||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||||
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
}
|
||||
|
||||
// pop off stack
|
||||
if (len) {
|
||||
stack = stack.slice(0,-1*len*2);
|
||||
vstack = vstack.slice(0, -1*len);
|
||||
lstack = lstack.slice(0, -1*len);
|
||||
}
|
||||
|
||||
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
// goto new state = table[STATE][NONTERMINAL]
|
||||
newState = table[stack[stack.length-2]][stack[stack.length-1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// accept
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}};
|
||||
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function(){
|
||||
var lexer = ({
|
||||
|
||||
EOF:1,
|
||||
|
||||
parseError:function parseError(str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
} else {
|
||||
throw new Error(str);
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput:function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input:function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput:function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
//this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more:function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject:function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less:function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput:function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput:function () {
|
||||
var next = this.match;
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition:function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match:function(match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
backup = {
|
||||
yylineno: this.yylineno,
|
||||
yylloc: {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.last_line,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: this.yylloc.last_column
|
||||
},
|
||||
yytext: this.yytext,
|
||||
match: this.match,
|
||||
matches: this.matches,
|
||||
matched: this.matched,
|
||||
yyleng: this.yyleng,
|
||||
offset: this.offset,
|
||||
_more: this._more,
|
||||
_input: this._input,
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next:function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex:function lex () {
|
||||
var r = this.next();
|
||||
if (r) {
|
||||
return r;
|
||||
} else {
|
||||
return this.lex();
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin:function begin (condition) {
|
||||
this.conditionStack.push(condition);
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState:function popState () {
|
||||
var n = this.conditionStack.length - 1;
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules:function _currentRules () {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState:function topState (n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
} else {
|
||||
return "INITIAL";
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState:function pushState (condition) {
|
||||
this.begin(condition);
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize:function stateStackSize() {
|
||||
return this.conditionStack.length;
|
||||
},
|
||||
options: {},
|
||||
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
|
||||
var YYSTATE=YY_START;
|
||||
switch($avoiding_name_collisions) {
|
||||
case 0:/* skip whitespace */
|
||||
break;
|
||||
case 1:return 8;
|
||||
break;
|
||||
case 2:return 8;
|
||||
break;
|
||||
case 3:return 21;
|
||||
break;
|
||||
case 4:return 35;
|
||||
break;
|
||||
case 5:return 24;
|
||||
break;
|
||||
case 6:return 26;
|
||||
break;
|
||||
case 7:return 26;
|
||||
break;
|
||||
case 8:return 25;
|
||||
break;
|
||||
case 9:return 21;
|
||||
break;
|
||||
case 10:return 31;
|
||||
break;
|
||||
case 11:return 31;
|
||||
break;
|
||||
case 12:return 33;
|
||||
break;
|
||||
case 13:return 28;
|
||||
break;
|
||||
case 14:return 9;
|
||||
break;
|
||||
case 15:return ' ';
|
||||
break;
|
||||
case 16:return 32;
|
||||
break;
|
||||
case 17:return 27;
|
||||
break;
|
||||
case 18:return 29;
|
||||
break;
|
||||
case 19:return 30;
|
||||
break;
|
||||
case 20:return 18;
|
||||
break;
|
||||
case 21:return 19;
|
||||
break;
|
||||
case 22:return 17;
|
||||
break;
|
||||
case 23:return 11;
|
||||
break;
|
||||
case 24:return 20;
|
||||
break;
|
||||
case 25:return 12;
|
||||
break;
|
||||
case 26:return 13;
|
||||
break;
|
||||
case 27:return 15;
|
||||
break;
|
||||
case 28:return 14;
|
||||
break;
|
||||
case 29:return 16;
|
||||
break;
|
||||
case 30:return '"';
|
||||
break;
|
||||
case 31:return "'";
|
||||
break;
|
||||
case 32:return "!";
|
||||
break;
|
||||
case 33:return 10;
|
||||
break;
|
||||
case 34:return 34;
|
||||
break;
|
||||
case 35:return '#';
|
||||
break;
|
||||
case 36:return 5;
|
||||
break;
|
||||
}
|
||||
},
|
||||
rules: [/^(?:\s+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9\.]+(?=[(]))/,/^(?:#[A-Z0-9\/]+(!|\?)?)/,/^(?:\$[A-Za-z]+\$[0-9]+)/,/^(?:\$[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z]+\$[0-9]+)/,/^(?:[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z\.]+(?=[(]))/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+)/,/^(?:[A-Za-z_]+)/,/^(?:[0-9]+)/,/^(?:\[(.*)?\])/,/^(?:&)/,/^(?: )/,/^(?:[.])/,/^(?::)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\/)/,/^(?:-)/,/^(?:\+)/,/^(?:\^)/,/^(?:\()/,/^(?:\))/,/^(?:>)/,/^(?:<)/,/^(?:NOT\b)/,/^(?:")/,/^(?:')/,/^(?:!)/,/^(?:=)/,/^(?:%)/,/^(?:[#])/,/^(?:$)/],
|
||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
@@ -0,0 +1,876 @@
|
||||
// Provenance: handsontable/formula-parser (vuln).
|
||||
// repo: handsontable/formula-parser
|
||||
// commit: 944136096f44ff4ffd4ba0bcef30970ca4702fce
|
||||
// parent: 944136096f44ff4ffd4ba0bcef30970ca4702fce
|
||||
// commit_url: https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e
|
||||
// cve: CVE-2020-6836
|
||||
// license: MIT
|
||||
// function: performAction
|
||||
// relpath: src/grammar-parser/grammar-parser.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 74
|
||||
|
||||
var grammarParser = (function(){
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,8],$V2=[1,6],$V3=[1,7],$V4=[1,9],$V5=[1,14],$V6=[1,15],$V7=[1,16],$V8=[1,12],$V9=[1,13],$Va=[1,17],$Vb=[1,19],$Vc=[1,20],$Vd=[1,21],$Ve=[1,22],$Vf=[1,23],$Vg=[1,24],$Vh=[1,25],$Vi=[1,26],$Vj=[1,27],$Vk=[1,28],$Vl=[5,9,10,11,13,14,15,16,17,18,19,20,29,30],$Vm=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,32],$Vn=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,34],$Vo=[5,10,11,13,14,15,16,17,29,30],$Vp=[5,10,13,14,15,16,29,30],$Vq=[5,10,11,13,14,15,16,17,18,19,29,30],$Vr=[13,29,30];
|
||||
var parser = {trace: function trace() { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"expressions":3,"expression":4,"EOF":5,"variableSequence":6,"number":7,"STRING":8,"&":9,"=":10,"+":11,"(":12,")":13,"<":14,">":15,"NOT":16,"-":17,"*":18,"/":19,"^":20,"FUNCTION":21,"expseq":22,"cell":23,"ABSOLUTE_CELL":24,"RELATIVE_CELL":25,"MIXED_CELL":26,":":27,"ARRAY":28,";":29,",":30,"VARIABLE":31,"DECIMAL":32,"NUMBER":33,"%":34,"ERROR":35,"$accept":0,"$end":1},
|
||||
terminals_: {5:"EOF",8:"STRING",9:"&",10:"=",11:"+",12:"(",13:")",14:"<",15:">",16:"NOT",17:"-",18:"*",19:"/",20:"^",21:"FUNCTION",24:"ABSOLUTE_CELL",25:"RELATIVE_CELL",26:"MIXED_CELL",27:":",28:"ARRAY",29:";",30:",",31:"VARIABLE",32:"DECIMAL",33:"NUMBER",34:"%",35:"ERROR"},
|
||||
productions_: [0,[3,2],[4,1],[4,1],[4,1],[4,3],[4,3],[4,3],[4,3],[4,4],[4,4],[4,4],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,2],[4,2],[4,3],[4,4],[4,1],[4,1],[4,2],[23,1],[23,1],[23,1],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[22,1],[22,1],[22,3],[22,3],[6,1],[6,3],[7,1],[7,3],[7,2],[2,1]],
|
||||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
switch (yystate) {
|
||||
case 1:
|
||||
|
||||
return $$[$0-1];
|
||||
|
||||
break;
|
||||
case 2:
|
||||
|
||||
this.$ = yy.callVariable($$[$0][0]);
|
||||
|
||||
break;
|
||||
case 3:
|
||||
|
||||
this.$ = yy.toNumber($$[$0]);
|
||||
|
||||
break;
|
||||
case 4:
|
||||
|
||||
this.$ = yy.trimEdges($$[$0]);
|
||||
|
||||
break;
|
||||
case 5:
|
||||
|
||||
this.$ = yy.evaluateByOperator('&', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 6:
|
||||
|
||||
this.$ = yy.evaluateByOperator('=', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 7:
|
||||
|
||||
this.$ = yy.evaluateByOperator('+', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 8:
|
||||
|
||||
this.$ = $$[$0-1];
|
||||
|
||||
break;
|
||||
case 9:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 10:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 11:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<>', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 12:
|
||||
|
||||
this.$ = yy.evaluateByOperator('NOT', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 13:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 14:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 15:
|
||||
|
||||
this.$ = yy.evaluateByOperator('-', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 16:
|
||||
|
||||
this.$ = yy.evaluateByOperator('*', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 17:
|
||||
|
||||
this.$ = yy.evaluateByOperator('/', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 18:
|
||||
|
||||
this.$ = yy.evaluateByOperator('^', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 19:
|
||||
|
||||
var n1 = yy.invertNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 20:
|
||||
|
||||
var n1 = yy.toNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 21:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-2]);
|
||||
|
||||
break;
|
||||
case 22:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-3], $$[$0-1]);
|
||||
|
||||
break;
|
||||
case 26: case 27: case 28:
|
||||
|
||||
this.$ = yy.cellValue($$[$0]);
|
||||
|
||||
break;
|
||||
case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
|
||||
|
||||
this.$ = yy.rangeValue($$[$0-2], $$[$0]);
|
||||
|
||||
break;
|
||||
case 38: case 42:
|
||||
|
||||
this.$ = [$$[$0]];
|
||||
|
||||
break;
|
||||
case 39:
|
||||
|
||||
var result = [];
|
||||
var arr = eval("[" + yytext + "]");
|
||||
|
||||
arr.forEach(function(item) {
|
||||
result.push(item);
|
||||
});
|
||||
|
||||
this.$ = result;
|
||||
|
||||
break;
|
||||
case 40: case 41:
|
||||
|
||||
$$[$0-2].push($$[$0]);
|
||||
this.$ = $$[$0-2];
|
||||
|
||||
break;
|
||||
case 43:
|
||||
|
||||
this.$ = (Array.isArray($$[$0-2]) ? $$[$0-2] : [$$[$0-2]]);
|
||||
this.$.push($$[$0]);
|
||||
|
||||
break;
|
||||
case 44:
|
||||
|
||||
this.$ = $$[$0];
|
||||
|
||||
break;
|
||||
case 45:
|
||||
|
||||
this.$ = ($$[$0-2] + '.' + $$[$0]) * 1;
|
||||
|
||||
break;
|
||||
case 46:
|
||||
|
||||
this.$ = $$[$0-1] * 0.01;
|
||||
|
||||
break;
|
||||
case 47:
|
||||
|
||||
this.$ = yy.throwError($$[$0]);
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
table: [{2:11,3:1,4:2,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{1:[3]},{5:[1,18],9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vl,[2,2],{32:[1,29]}),o($Vl,[2,3],{34:[1,30]}),o($Vl,[2,4]),{2:11,4:31,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:32,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:33,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{12:[1,34]},o($Vl,[2,23]),o($Vl,[2,24],{2:35,35:$Va}),o($Vm,[2,42]),o($Vn,[2,44],{32:[1,36]}),o($Vl,[2,26],{27:[1,37]}),o($Vl,[2,27],{27:[1,38]}),o($Vl,[2,28],{27:[1,39]}),o([5,9,10,11,13,14,15,16,17,18,19,20,29,30,35],[2,47]),{1:[2,1]},{2:11,4:40,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:41,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:42,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:45,6:3,7:4,8:$V0,10:[1,43],11:$V1,12:$V2,15:[1,44],17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:47,6:3,7:4,8:$V0,10:[1,46],11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:48,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:49,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:50,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:51,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:52,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{31:[1,53]},o($Vn,[2,46]),{9:$Vb,10:$Vc,11:$Vd,13:[1,54],14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vo,[2,19],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,20],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:57,6:3,7:4,8:$V0,11:$V1,12:$V2,13:[1,55],17:$V3,21:$V4,22:56,23:10,24:$V5,25:$V6,26:$V7,28:[1,58],31:$V8,33:$V9,35:$Va},o($Vl,[2,25]),{33:[1,59]},{24:[1,60],25:[1,61],26:[1,62]},{24:[1,63],25:[1,64],26:[1,65]},{24:[1,66],25:[1,67],26:[1,68]},o($Vl,[2,5]),o([5,10,13,29,30],[2,6],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,7],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:69,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:70,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,14],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:71,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,13],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o([5,10,13,16,29,30],[2,12],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,15],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vq,[2,16],{9:$Vb,20:$Vk}),o($Vq,[2,17],{9:$Vb,20:$Vk}),o([5,10,11,13,14,15,16,17,18,19,20,29,30],[2,18],{9:$Vb}),o($Vm,[2,43]),o($Vl,[2,8]),o($Vl,[2,21]),{13:[1,72],29:[1,73],30:[1,74]},o($Vr,[2,38],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,39]),o($Vn,[2,45]),o($Vl,[2,29]),o($Vl,[2,30]),o($Vl,[2,31]),o($Vl,[2,32]),o($Vl,[2,33]),o($Vl,[2,34]),o($Vl,[2,35]),o($Vl,[2,36]),o($Vl,[2,37]),o($Vp,[2,9],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,11],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,10],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vl,[2,22]),{2:11,4:75,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:76,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vr,[2,40],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,41],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk})],
|
||||
defaultActions: {18:[2,1]},
|
||||
parseError: function parseError(str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
} else {
|
||||
function _parseError (msg, hash) {
|
||||
this.message = msg;
|
||||
this.hash = hash;
|
||||
}
|
||||
_parseError.prototype = Error;
|
||||
|
||||
throw new _parseError(str, hash);
|
||||
}
|
||||
},
|
||||
parse: function parse(input) {
|
||||
var self = this,
|
||||
stack = [0],
|
||||
tstack = [], // token stack
|
||||
vstack = [null], // semantic value stack
|
||||
lstack = [], // location stack
|
||||
table = this.table,
|
||||
yytext = '',
|
||||
yylineno = 0,
|
||||
yyleng = 0,
|
||||
recovering = 0,
|
||||
TERROR = 2,
|
||||
EOF = 1;
|
||||
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
|
||||
//this.reductionCount = this.shiftCount = 0;
|
||||
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
// copy state
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
}
|
||||
}
|
||||
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
}
|
||||
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
}
|
||||
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
// if token isn't its numeric value, convert
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
while (true) {
|
||||
// retreive state number from top of stack
|
||||
state = stack[stack.length - 1];
|
||||
|
||||
// use default actions if available
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
}
|
||||
// read action for current state and first input
|
||||
action = table[state] && table[state][symbol];
|
||||
}
|
||||
|
||||
// handle parse error
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var error_rule_depth;
|
||||
var errStr = '';
|
||||
|
||||
// Return the rule stack depth where the nearest error rule can be found.
|
||||
// Return FALSE when no error recovery rule was found.
|
||||
function locateNearestErrorRecoveryRule(state) {
|
||||
var stack_probe = stack.length - 1;
|
||||
var depth = 0;
|
||||
|
||||
// try to recover from error
|
||||
for(;;) {
|
||||
// check for error recovery rule in this state
|
||||
if ((TERROR.toString()) in table[state]) {
|
||||
return depth;
|
||||
}
|
||||
if (state === 0 || stack_probe < 2) {
|
||||
return false; // No suitable error recovery rule available.
|
||||
}
|
||||
stack_probe -= 2; // popStack(1): [symbol, action]
|
||||
state = stack[stack_probe];
|
||||
++depth;
|
||||
}
|
||||
}
|
||||
|
||||
if (!recovering) {
|
||||
// first see if there's any chance at hitting an error recovery rule:
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
|
||||
// Report error
|
||||
expected = [];
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push("'"+this.terminals_[p]+"'");
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+":\n"+lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol)+ "'";
|
||||
} else {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
|
||||
(symbol == EOF ? "end of input" :
|
||||
("'"+(this.terminals_[symbol] || symbol)+"'"));
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
token: this.terminals_[symbol] || symbol,
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected,
|
||||
recoverable: (error_rule_depth !== false)
|
||||
});
|
||||
} else if (preErrorSymbol !== EOF) {
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
}
|
||||
|
||||
// just recovered from another error
|
||||
if (recovering == 3) {
|
||||
if (symbol === EOF || preErrorSymbol === EOF) {
|
||||
throw new Error(errStr || 'Parsing halted while starting to recover from another error.');
|
||||
}
|
||||
|
||||
// discard current lookahead and grab another
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
symbol = lex();
|
||||
}
|
||||
|
||||
// try to recover from error
|
||||
if (error_rule_depth === false) {
|
||||
throw new Error(errStr || 'Parsing halted. No suitable error recovery rule available.');
|
||||
}
|
||||
popStack(error_rule_depth);
|
||||
|
||||
preErrorSymbol = (symbol == TERROR ? null : symbol); // save the lookahead token
|
||||
symbol = TERROR; // insert generic error symbol as new lookahead
|
||||
state = stack[stack.length-1];
|
||||
action = table[state] && table[state][TERROR];
|
||||
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
|
||||
}
|
||||
|
||||
// this shouldn't happen, unless resolve defaults are off
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
|
||||
}
|
||||
|
||||
switch (action[0]) {
|
||||
case 1: // shift
|
||||
//this.shiftCount++;
|
||||
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]); // push state
|
||||
symbol = null;
|
||||
if (!preErrorSymbol) { // normal execution/no error
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
}
|
||||
} else {
|
||||
// error just occurred, resume old lookahead f/ before error
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// reduce
|
||||
//this.reductionCount++;
|
||||
|
||||
len = this.productions_[action[1]][1];
|
||||
|
||||
// perform semantic action
|
||||
yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
|
||||
// default location, uses first token for firsts, last for lasts
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length-(len||1)].first_line,
|
||||
last_line: lstack[lstack.length-1].last_line,
|
||||
first_column: lstack[lstack.length-(len||1)].first_column,
|
||||
last_column: lstack[lstack.length-1].last_column
|
||||
};
|
||||
if (ranges) {
|
||||
yyval._$.range = [lstack[lstack.length-(len||1)].range[0], lstack[lstack.length-1].range[1]];
|
||||
}
|
||||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||||
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
}
|
||||
|
||||
// pop off stack
|
||||
if (len) {
|
||||
stack = stack.slice(0,-1*len*2);
|
||||
vstack = vstack.slice(0, -1*len);
|
||||
lstack = lstack.slice(0, -1*len);
|
||||
}
|
||||
|
||||
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
// goto new state = table[STATE][NONTERMINAL]
|
||||
newState = table[stack[stack.length-2]][stack[stack.length-1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// accept
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}};
|
||||
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function(){
|
||||
var lexer = ({
|
||||
|
||||
EOF:1,
|
||||
|
||||
parseError:function parseError(str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
} else {
|
||||
throw new Error(str);
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput:function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input:function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput:function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
//this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more:function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject:function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less:function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput:function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput:function () {
|
||||
var next = this.match;
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition:function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match:function (match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
backup = {
|
||||
yylineno: this.yylineno,
|
||||
yylloc: {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.last_line,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: this.yylloc.last_column
|
||||
},
|
||||
yytext: this.yytext,
|
||||
match: this.match,
|
||||
matches: this.matches,
|
||||
matched: this.matched,
|
||||
yyleng: this.yyleng,
|
||||
offset: this.offset,
|
||||
_more: this._more,
|
||||
_input: this._input,
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next:function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex:function lex() {
|
||||
var r = this.next();
|
||||
if (r) {
|
||||
return r;
|
||||
} else {
|
||||
return this.lex();
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin:function begin(condition) {
|
||||
this.conditionStack.push(condition);
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState:function popState() {
|
||||
var n = this.conditionStack.length - 1;
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules:function _currentRules() {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState:function topState(n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
} else {
|
||||
return "INITIAL";
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState:function pushState(condition) {
|
||||
this.begin(condition);
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize:function stateStackSize() {
|
||||
return this.conditionStack.length;
|
||||
},
|
||||
options: {},
|
||||
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
|
||||
var YYSTATE=YY_START;
|
||||
switch($avoiding_name_collisions) {
|
||||
case 0:/* skip whitespace */
|
||||
break;
|
||||
case 1:return 8;
|
||||
break;
|
||||
case 2:return 8;
|
||||
break;
|
||||
case 3:return 21;
|
||||
break;
|
||||
case 4:return 35;
|
||||
break;
|
||||
case 5:return 24;
|
||||
break;
|
||||
case 6:return 26;
|
||||
break;
|
||||
case 7:return 26;
|
||||
break;
|
||||
case 8:return 25;
|
||||
break;
|
||||
case 9:return 21;
|
||||
break;
|
||||
case 10:return 31;
|
||||
break;
|
||||
case 11:return 31;
|
||||
break;
|
||||
case 12:return 33;
|
||||
break;
|
||||
case 13:return 28;
|
||||
break;
|
||||
case 14:return 9;
|
||||
break;
|
||||
case 15:return ' ';
|
||||
break;
|
||||
case 16:return 32;
|
||||
break;
|
||||
case 17:return 27;
|
||||
break;
|
||||
case 18:return 29;
|
||||
break;
|
||||
case 19:return 30;
|
||||
break;
|
||||
case 20:return 18;
|
||||
break;
|
||||
case 21:return 19;
|
||||
break;
|
||||
case 22:return 17;
|
||||
break;
|
||||
case 23:return 11;
|
||||
break;
|
||||
case 24:return 20;
|
||||
break;
|
||||
case 25:return 12;
|
||||
break;
|
||||
case 26:return 13;
|
||||
break;
|
||||
case 27:return 15;
|
||||
break;
|
||||
case 28:return 14;
|
||||
break;
|
||||
case 29:return 16;
|
||||
break;
|
||||
case 30:return '"';
|
||||
break;
|
||||
case 31:return "'";
|
||||
break;
|
||||
case 32:return "!";
|
||||
break;
|
||||
case 33:return 10;
|
||||
break;
|
||||
case 34:return 34;
|
||||
break;
|
||||
case 35:return '#';
|
||||
break;
|
||||
case 36:return 5;
|
||||
break;
|
||||
}
|
||||
},
|
||||
rules: [/^(?:\s+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9\.]+(?=[(]))/,/^(?:#[A-Z0-9\/]+(!|\?)?)/,/^(?:\$[A-Za-z]+\$[0-9]+)/,/^(?:\$[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z]+\$[0-9]+)/,/^(?:[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z\.]+(?=[(]))/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+)/,/^(?:[A-Za-z_]+)/,/^(?:[0-9]+)/,/^(?:\[(.*)?\])/,/^(?:&)/,/^(?: )/,/^(?:[.])/,/^(?::)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\/)/,/^(?:-)/,/^(?:\+)/,/^(?:\^)/,/^(?:\()/,/^(?:\))/,/^(?:>)/,/^(?:<)/,/^(?:NOT\b)/,/^(?:")/,/^(?:')/,/^(?:!)/,/^(?:=)/,/^(?:%)/,/^(?:[#])/,/^(?:$)/],
|
||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
@@ -0,0 +1,234 @@
|
||||
// Provenance: jas-/node-libnmap (fixed).
|
||||
// repo: jas-/node-libnmap
|
||||
// commit: c235b24b0342e12a5dbf502f89daabe95883b6c8
|
||||
// parent: 49b72239b144ab7ffdf673b62e18bfd0760948f6
|
||||
// commit_url: https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8
|
||||
// cve: CVE-2018-16461
|
||||
// license: MIT
|
||||
// function: block
|
||||
// relpath: lib/classes/tools.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 20
|
||||
|
||||
class tools extends emitter {
|
||||
|
||||
/**
|
||||
* @function merge
|
||||
* Perform preliminary option/default object merge
|
||||
*
|
||||
* @param {Object} defaults Application defaults
|
||||
* @param {Object} obj User supplied object
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
merge(defaults, obj) {
|
||||
return merge(defaults, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function chunk
|
||||
* Defines new property for array's
|
||||
*
|
||||
* @param {Array} obj Supplied array
|
||||
* @param {Integer} offset Supplied offset
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
chunk(obj, offset) {
|
||||
let idx = 0;
|
||||
const alength = obj.length;
|
||||
const tarray = [];
|
||||
|
||||
for (idx = 0; idx < alength; idx += offset) {
|
||||
tarray.push(obj.slice(idx, idx + offset).join(' '));
|
||||
}
|
||||
|
||||
return tarray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function flatten
|
||||
* Flattens nested arrays into one flat array
|
||||
*
|
||||
* @param {Array} arr Array combinator
|
||||
* @param {Array} obj User supplied array
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
flatten(arr, obj) {
|
||||
let value;
|
||||
const result = [];
|
||||
|
||||
for (let i = 0, length = arr.length; i < length; i++) {
|
||||
|
||||
value = arr[i];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return this.flatten(value, obj);
|
||||
}
|
||||
else {
|
||||
result.push(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function funcs
|
||||
* Create functions for use as callbacks
|
||||
*
|
||||
* @param {Obect} opts Application defaults
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
funcs(opts) {
|
||||
const scope = this;
|
||||
const funcs = {};
|
||||
let cmd = false;
|
||||
const errors = [];
|
||||
const reports = [];
|
||||
|
||||
if (opts.range.length <= 0)
|
||||
return "Range of hosts could not be created";
|
||||
|
||||
Object.keys(opts.range).forEach(function blocks(block) {
|
||||
|
||||
// Acquire an array of ranges
|
||||
const range = opts.range[block];
|
||||
|
||||
// Create a new function for each range block
|
||||
funcs[range] = function block(callback) {
|
||||
const report = [];
|
||||
|
||||
|
||||
// Capture the flags, & ranges as a command string
|
||||
cmd = scope.command(opts, range);
|
||||
|
||||
// Split up cmd for .spawn()
|
||||
const obj = cmd.split(" ");
|
||||
cmd = obj[0];
|
||||
const args = obj.slice(1);
|
||||
|
||||
if (opts.verbose)
|
||||
console.log(`Running: ${cmd}`);
|
||||
|
||||
// Push it on to the heap
|
||||
const execute = proc(cmd, args);
|
||||
|
||||
// Discard stderr for now, maybe log?
|
||||
execute.stderr.on('data', (chunk) => {
|
||||
/* Silently discard stderr messages to not interupt scans */
|
||||
});
|
||||
|
||||
// Push to array of reports
|
||||
execute.stdout.on('data', (chunk) => {
|
||||
report.push(chunk);
|
||||
});
|
||||
|
||||
// Push report array to reporting function on stream end
|
||||
execute.stdout.on('end', () => {
|
||||
if (report.length > 0)
|
||||
return reporting.reports(opts, report, callback);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function command
|
||||
* Generate nmap command string
|
||||
*
|
||||
* @param {Object} opts - User supplied options
|
||||
* @param {String} block - Network block
|
||||
*
|
||||
* @returns {String} NMAP scan string
|
||||
*/
|
||||
command(opts, block) {
|
||||
const flags = opts.flags.join(' ');
|
||||
const proto = (opts.udp) ? ' -sU' : ' ';
|
||||
const to = `--host-timeout=${opts.timeout}s `;
|
||||
const ipv6 = (validation.test(validation.patterns.IPv6, block)) ?
|
||||
' -6 ' : ' ';
|
||||
|
||||
return (opts.ports) ?
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}-p${opts.ports} ${block}` :
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}${block}`;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function worker
|
||||
* Executes object of functions
|
||||
*
|
||||
* @param {Object} obj User supplied object
|
||||
* @param {Function} fn Return function
|
||||
*/
|
||||
worker(obj, fn) {
|
||||
async.parallelLimit(obj.funcs, obj.threshold, fn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function init
|
||||
* @scope private
|
||||
* Merges supplied options & builds functions
|
||||
*
|
||||
* @param {Object} defaults libnmap default options
|
||||
* @param {Object} opts User supplied configuration object
|
||||
* @param {Function} cb Callback
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
init(defaults, opts, cb) {
|
||||
let funcs = [];
|
||||
const ranges = [];
|
||||
const called = caller.get()[1].getFunctionName();
|
||||
|
||||
/* Override 'defaults.flags' array with 'opts.flags' (prevents merge) */
|
||||
if (/array/.test(typeof opts.flags))
|
||||
defaults.flags = opts.flags;
|
||||
|
||||
opts = this.merge(defaults, opts);
|
||||
|
||||
/* Ensure we can always parse the report */
|
||||
if (opts.flags.indexOf('-oX -') === -1)
|
||||
opts.flags.push('-oX -');
|
||||
|
||||
/* If we are in a discover mode get adapters for associated network(s) */
|
||||
if (/nmap.discover/.test(called)) {
|
||||
|
||||
/* Bail early if we cannot determine any ranges */
|
||||
if (!(opts.range = network.adapters(opts)))
|
||||
return cb(validation.messages.version);
|
||||
|
||||
/* Set scan options as static values for 'discover' mode */
|
||||
opts.ports = '';
|
||||
opts.flags = [
|
||||
'-n',
|
||||
'-oX -',
|
||||
'-sn',
|
||||
'-PR'
|
||||
];
|
||||
}
|
||||
|
||||
validation.init(opts, (err, result) => {
|
||||
if (err)
|
||||
return cb(err);
|
||||
|
||||
opts.range = network.calculate(opts);
|
||||
funcs = this.funcs(opts);
|
||||
|
||||
return cb(null, {
|
||||
opts,
|
||||
funcs
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
// Provenance: jas-/node-libnmap (vuln).
|
||||
// repo: jas-/node-libnmap
|
||||
// commit: 49b72239b144ab7ffdf673b62e18bfd0760948f6
|
||||
// parent: 49b72239b144ab7ffdf673b62e18bfd0760948f6
|
||||
// commit_url: https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8
|
||||
// cve: CVE-2018-16461
|
||||
// license: MIT
|
||||
// function: block
|
||||
// relpath: lib/classes/tools.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 20
|
||||
|
||||
class tools extends emitter {
|
||||
|
||||
/**
|
||||
* @function merge
|
||||
* Perform preliminary option/default object merge
|
||||
*
|
||||
* @param {Object} defaults Application defaults
|
||||
* @param {Object} obj User supplied object
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
merge(defaults, obj) {
|
||||
return merge(defaults, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function chunk
|
||||
* Defines new property for array's
|
||||
*
|
||||
* @param {Array} obj Supplied array
|
||||
* @param {Integer} offset Supplied offset
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
chunk(obj, offset) {
|
||||
let idx = 0;
|
||||
const alength = obj.length;
|
||||
const tarray = [];
|
||||
|
||||
for (idx = 0; idx < alength; idx += offset) {
|
||||
tarray.push(obj.slice(idx, idx + offset).join(' '));
|
||||
}
|
||||
|
||||
return tarray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function flatten
|
||||
* Flattens nested arrays into one flat array
|
||||
*
|
||||
* @param {Array} arr Array combinator
|
||||
* @param {Array} obj User supplied array
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
flatten(arr, obj) {
|
||||
let value;
|
||||
const result = [];
|
||||
|
||||
for (let i = 0, length = arr.length; i < length; i++) {
|
||||
|
||||
value = arr[i];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return this.flatten(value, obj);
|
||||
} else {
|
||||
result.push(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function funcs
|
||||
* Create functions for use as callbacks
|
||||
*
|
||||
* @param {Obect} opts Application defaults
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
funcs(opts) {
|
||||
const scope = this;
|
||||
const funcs = {};
|
||||
let cmd = false;
|
||||
const errors = [];
|
||||
const reports = [];
|
||||
|
||||
if (opts.range.length <= 0)
|
||||
return "Range of hosts could not be created";
|
||||
|
||||
Object.keys(opts.range).forEach(function blocks(block) {
|
||||
|
||||
const range = opts.range[block];
|
||||
funcs[range] = function block(callback) {
|
||||
cmd = scope.command(opts, range);
|
||||
|
||||
if (opts.verbose)
|
||||
console.log(`Running: ${cmd}`);
|
||||
|
||||
const report = [];
|
||||
|
||||
const execute = proc(cmd, (err, stdout, stderr) => {
|
||||
if (err)
|
||||
return reporting.reports(opts, err, callback);
|
||||
});
|
||||
|
||||
execute.stderr.on('data', (chunk) => {
|
||||
/* Silently discard stderr messages to not interupt scans */
|
||||
});
|
||||
|
||||
execute.stdout.on('data', (chunk) => {
|
||||
report.push(chunk);
|
||||
});
|
||||
|
||||
execute.stdout.on('end', () => {
|
||||
if (report.length > 0)
|
||||
return reporting.reports(opts, report, callback);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function command
|
||||
* Generate nmap command string
|
||||
*
|
||||
* @param {Object} opts - User supplied options
|
||||
* @param {String} block - Network block
|
||||
*
|
||||
* @returns {String} NMAP scan string
|
||||
*/
|
||||
command(opts, block) {
|
||||
const flags = opts.flags.join(' ');
|
||||
const proto = (opts.udp) ? ' -sU' : ' ';
|
||||
const to = `--host-timeout=${opts.timeout}s `;
|
||||
const ipv6 = (validation.test(validation.patterns.IPv6, block)) ?
|
||||
' -6 ' : ' ';
|
||||
|
||||
return (opts.ports) ?
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}-p${opts.ports} ${block}` :
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}${block}`;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function worker
|
||||
* Executes object of functions
|
||||
*
|
||||
* @param {Object} obj User supplied object
|
||||
* @param {Function} fn Return function
|
||||
*/
|
||||
worker(obj, fn) {
|
||||
async.parallelLimit(obj.funcs, obj.threshold, fn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function init
|
||||
* @scope private
|
||||
* Merges supplied options & builds functions
|
||||
*
|
||||
* @param {Object} defaults libnmap default options
|
||||
* @param {Object} opts User supplied configuration object
|
||||
* @param {Function} cb Callback
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
init(defaults, opts, cb) {
|
||||
let funcs = [];
|
||||
const ranges = [];
|
||||
const called = caller.get()[1].getFunctionName();
|
||||
|
||||
/* Override 'defaults.flags' array with 'opts.flags' (prevents merge) */
|
||||
if (/array/.test(typeof opts.flags))
|
||||
defaults.flags = opts.flags;
|
||||
|
||||
opts = this.merge(defaults, opts);
|
||||
|
||||
/* Ensure we can always parse the report */
|
||||
if (opts.flags.indexOf('-oX -') === -1)
|
||||
opts.flags.push('-oX -');
|
||||
|
||||
/* If we are in a discover mode get adapters for associated network(s) */
|
||||
if (/nmap.discover/.test(called)) {
|
||||
|
||||
/* Bail early if we cannot determine any ranges */
|
||||
if (!(opts.range = network.adapters(opts)))
|
||||
return cb(validation.messages.version);
|
||||
|
||||
/* Set scan options as static values for 'discover' mode */
|
||||
opts.ports = '';
|
||||
opts.flags = [
|
||||
'-n',
|
||||
'-oX -',
|
||||
'-sn',
|
||||
'-PR'
|
||||
];
|
||||
}
|
||||
|
||||
validation.init(opts, (err, result) => {
|
||||
if (err)
|
||||
return cb(err);
|
||||
|
||||
opts.range = network.calculate(opts);
|
||||
funcs = this.funcs(opts);
|
||||
|
||||
return cb(null, {
|
||||
opts,
|
||||
funcs
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
// Provenance: roest01/node-pdf-image (fixed).
|
||||
// repo: roest01/node-pdf-image
|
||||
// commit: 54679496a89738443917608c2bbe2f6e5dd20e83
|
||||
// parent: d8c0dcadd93985dbefe80b84060f5f572bfbb6ff
|
||||
// commit_url: https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83
|
||||
// cve: CVE-2018-3757
|
||||
// license: MIT
|
||||
// function: getInfo
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 24
|
||||
|
||||
PDFImage.prototype = {
|
||||
constructGetInfoCommand: function () {
|
||||
return {
|
||||
cmd: "pdfinfo",
|
||||
args: [this.pdfFilePath]
|
||||
};
|
||||
},
|
||||
parseGetInfoCommandOutput: function (output) {
|
||||
var info = {};
|
||||
output.split("\n").forEach(function (line) {
|
||||
if (line.match(/^(.*?):[ \t]*(.*)$/)) {
|
||||
info[RegExp.$1] = RegExp.$2;
|
||||
}
|
||||
});
|
||||
return info;
|
||||
},
|
||||
getInfo: function () {
|
||||
var self = this;
|
||||
var getInfoCommand = this.constructGetInfoCommand();
|
||||
return new Promise(function (resolve, reject) {
|
||||
spawn(getInfoCommand.cmd, getInfoCommand.args, { capture: [ 'stdout', 'stderr' ]})
|
||||
.then(function (cmdResult) {
|
||||
resolve(self.parseGetInfoCommandOutput(cmdResult.stdout.toString()));
|
||||
}).catch(reject);
|
||||
});
|
||||
},
|
||||
numberOfPages: function () {
|
||||
return this.getInfo().then(function (info) {
|
||||
return info["Pages"];
|
||||
});
|
||||
},
|
||||
getOutputImagePathForPage: function (pageNumber) {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "-" + pageNumber + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
getOutputImagePathForFile: function () {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
setConvertOptions: function (convertOptions) {
|
||||
this.convertOptions = convertOptions || {};
|
||||
},
|
||||
setPdfFileBaseName: function(pdfFileBaseName) {
|
||||
this.pdfFileBaseName = pdfFileBaseName || path.basename(this.pdfFilePath, ".pdf");
|
||||
},
|
||||
setConvertExtension: function (convertExtension) {
|
||||
this.convertExtension = convertExtension || "png";
|
||||
},
|
||||
constructConvertCommandForPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertOptions = this.constructConvertOptions();
|
||||
var args = [];
|
||||
if (convertOptions) args = convertOptions.slice();
|
||||
args.push(pdfFilePath+"["+pageNumber+"]");
|
||||
args.push(outputImagePath);
|
||||
|
||||
return {
|
||||
cmd: this.useGM ? "gm convert" : "convert",
|
||||
args: args
|
||||
};
|
||||
},
|
||||
constructCombineCommandForFile: function (imagePaths) {
|
||||
var args = imagePaths.slice();
|
||||
args.push(this.getOutputImagePathForFile());
|
||||
args.unshift("-append");
|
||||
return {
|
||||
cmd: this.useGM ? "gm convert" : "convert",
|
||||
args: args
|
||||
};
|
||||
},
|
||||
constructConvertOptions: function () {
|
||||
var convertOptions = [];
|
||||
Object.keys(this.convertOptions).sort().map(function (optionName) {
|
||||
if (this.convertOptions[optionName] !== null) {
|
||||
convertOptions.push(optionName);
|
||||
convertOptions.push(this.convertOptions[optionName]);
|
||||
} else {
|
||||
convertOptions.push(optionName);
|
||||
}
|
||||
}, this);
|
||||
return convertOptions;
|
||||
},
|
||||
combineImages: function(imagePaths) {
|
||||
var pdfImage = this;
|
||||
var combineCommand = pdfImage.constructCombineCommandForFile(imagePaths);
|
||||
return new Promise(function (resolve, reject) {
|
||||
spawn(combineCommand.cmd, combineCommand.args, { capture: [ 'stdout', 'stderr' ]})
|
||||
.then(function () {
|
||||
spawn("rm", imagePaths); //cleanUp
|
||||
resolve(pdfImage.getOutputImagePathForFile());
|
||||
}).catch(function(error){
|
||||
reject({
|
||||
message: "Failed to combine images",
|
||||
error: error.message,
|
||||
stdout: error.stdout,
|
||||
stderr: error.stderr
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
convertFile: function () {
|
||||
var pdfImage = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
pdfImage.numberOfPages().then(function (totalPages) {
|
||||
var convertPromise = new Promise(function (resolve, reject){
|
||||
var imagePaths = [];
|
||||
for (var i = 0; i < totalPages; i++) {
|
||||
pdfImage.convertPage(i).then(function(imagePath){
|
||||
imagePaths.push(imagePath);
|
||||
if (imagePaths.length === parseInt(totalPages)){
|
||||
imagePaths.sort(); //because of asyc pages we have to reSort pages
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
convertPromise.then(function(imagePaths){
|
||||
if (pdfImage.combinedImage){
|
||||
pdfImage.combineImages(imagePaths).then(function(imagePath){
|
||||
resolve(imagePath);
|
||||
});
|
||||
} else {
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
convertPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertCommand = this.constructConvertCommandForPage(pageNumber);
|
||||
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
function convertPageToImage() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
spawn(convertCommand.cmd, convertCommand.args, { capture: [ 'stdout', 'stderr' ]})
|
||||
.then(function () {
|
||||
resolve(outputImagePath);
|
||||
}).catch(function(error){
|
||||
reject({
|
||||
message: "Failed to convert page to image",
|
||||
error: error.message,
|
||||
stdout: error.stdout,
|
||||
stderr: error.stderr
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fs.stat(outputImagePath, function (err, imageFileStat) {
|
||||
var imageNotExists = err && err.code === "ENOENT";
|
||||
if (!imageNotExists && err) {
|
||||
return reject({
|
||||
message: "Failed to stat image file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
// convert when (1) image doesn't exits or (2) image exists
|
||||
// but its timestamp is older than pdf's one
|
||||
|
||||
if (imageNotExists) {
|
||||
// (1)
|
||||
convertPageToImage().then(function(result){
|
||||
resolve(result);
|
||||
}).catch(reject);
|
||||
return;
|
||||
}
|
||||
|
||||
// image exist. check timestamp.
|
||||
fs.stat(pdfFilePath, function (err, pdfFileStat) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to stat PDF file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
if (imageFileStat.mtime < pdfFileStat.mtime) {
|
||||
// (2)
|
||||
convertPageToImage().then(function(result){
|
||||
resolve(result);
|
||||
}).catch(reject);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,212 @@
|
||||
// Provenance: roest01/node-pdf-image (vuln).
|
||||
// repo: roest01/node-pdf-image
|
||||
// commit: d8c0dcadd93985dbefe80b84060f5f572bfbb6ff
|
||||
// parent: d8c0dcadd93985dbefe80b84060f5f572bfbb6ff
|
||||
// commit_url: https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83
|
||||
// cve: CVE-2018-3757
|
||||
// license: MIT
|
||||
// function: getInfo
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 24
|
||||
|
||||
PDFImage.prototype = {
|
||||
constructGetInfoCommand: function () {
|
||||
return util.format(
|
||||
"pdfinfo \"%s\"",
|
||||
this.pdfFilePath
|
||||
);
|
||||
},
|
||||
parseGetInfoCommandOutput: function (output) {
|
||||
var info = {};
|
||||
output.split("\n").forEach(function (line) {
|
||||
if (line.match(/^(.*?):[ \t]*(.*)$/)) {
|
||||
info[RegExp.$1] = RegExp.$2;
|
||||
}
|
||||
});
|
||||
return info;
|
||||
},
|
||||
getInfo: function () {
|
||||
var self = this;
|
||||
var getInfoCommand = this.constructGetInfoCommand();
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
exec(getInfoCommand, function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to get PDF'S information",
|
||||
error: err,
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
});
|
||||
}
|
||||
return resolve(self.parseGetInfoCommandOutput(stdout));
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
numberOfPages: function () {
|
||||
return this.getInfo().then(function (info) {
|
||||
return info["Pages"];
|
||||
});
|
||||
},
|
||||
getOutputImagePathForPage: function (pageNumber) {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "-" + pageNumber + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
getOutputImagePathForFile: function () {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
setConvertOptions: function (convertOptions) {
|
||||
this.convertOptions = convertOptions || {};
|
||||
},
|
||||
setPdfFileBaseName: function(pdfFileBaseName) {
|
||||
this.pdfFileBaseName = pdfFileBaseName || path.basename(this.pdfFilePath, ".pdf");
|
||||
},
|
||||
setConvertExtension: function (convertExtension) {
|
||||
this.convertExtension = convertExtension || "png";
|
||||
},
|
||||
constructConvertCommandForPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertOptionsString = this.constructConvertOptions();
|
||||
return util.format(
|
||||
"%s %s\"%s[%d]\" \"%s\"",
|
||||
this.useGM ? "gm convert" : "convert",
|
||||
convertOptionsString ? convertOptionsString + " " : "",
|
||||
pdfFilePath, pageNumber, outputImagePath
|
||||
);
|
||||
},
|
||||
constructCombineCommandForFile: function (imagePaths) {
|
||||
return util.format(
|
||||
"%s -append %s \"%s\"",
|
||||
this.useGM ? "gm convert" : "convert",
|
||||
imagePaths.join(' '),
|
||||
this.getOutputImagePathForFile()
|
||||
);
|
||||
},
|
||||
constructConvertOptions: function () {
|
||||
return Object.keys(this.convertOptions).sort().map(function (optionName) {
|
||||
if (this.convertOptions[optionName] !== null) {
|
||||
return optionName + " " + this.convertOptions[optionName];
|
||||
} else {
|
||||
return optionName;
|
||||
}
|
||||
}, this).join(" ");
|
||||
},
|
||||
combineImages: function(imagePaths) {
|
||||
var pdfImage = this;
|
||||
var combineCommand = pdfImage.constructCombineCommandForFile(imagePaths);
|
||||
return new Promise(function (resolve, reject) {
|
||||
exec(combineCommand, function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to combine images",
|
||||
error: err,
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
});
|
||||
}
|
||||
exec("rm "+imagePaths.join(' ')); //cleanUp
|
||||
return resolve(pdfImage.getOutputImagePathForFile());
|
||||
});
|
||||
});
|
||||
},
|
||||
convertFile: function () {
|
||||
var pdfImage = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
pdfImage.numberOfPages().then(function (totalPages) {
|
||||
var convertPromise = new Promise(function (resolve, reject){
|
||||
var imagePaths = [];
|
||||
for (var i = 0; i < totalPages; i++) {
|
||||
pdfImage.convertPage(i).then(function(imagePath){
|
||||
imagePaths.push(imagePath);
|
||||
if (imagePaths.length === parseInt(totalPages)){
|
||||
imagePaths.sort(); //because of asyc pages we have to reSort pages
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
convertPromise.then(function(imagePaths){
|
||||
if (pdfImage.combinedImage){
|
||||
pdfImage.combineImages(imagePaths).then(function(imagePath){
|
||||
resolve(imagePath);
|
||||
});
|
||||
} else {
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
convertPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertCommand = this.constructConvertCommandForPage(pageNumber);
|
||||
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
function convertPageToImage() {
|
||||
exec(convertCommand, function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to convert page to image",
|
||||
error: err,
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
});
|
||||
}
|
||||
return resolve(outputImagePath);
|
||||
});
|
||||
}
|
||||
|
||||
fs.stat(outputImagePath, function (err, imageFileStat) {
|
||||
var imageNotExists = err && err.code === "ENOENT";
|
||||
if (!imageNotExists && err) {
|
||||
return reject({
|
||||
message: "Failed to stat image file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
// convert when (1) image doesn't exits or (2) image exists
|
||||
// but its timestamp is older than pdf's one
|
||||
|
||||
if (imageNotExists) {
|
||||
// (1)
|
||||
convertPageToImage();
|
||||
return;
|
||||
}
|
||||
|
||||
// image exist. check timestamp.
|
||||
fs.stat(pdfFilePath, function (err, pdfFileStat) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to stat PDF file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
if (imageFileStat.mtime < pdfFileStat.mtime) {
|
||||
// (2)
|
||||
convertPageToImage();
|
||||
return;
|
||||
}
|
||||
|
||||
return resolve(outputImagePath);
|
||||
});
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,198 @@
|
||||
// Provenance: soyuka/pidusage (fixed).
|
||||
// repo: soyuka/pidusage
|
||||
// commit: b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d
|
||||
// parent: e3660d8a8e5e61afad9b02af67356a1e239d6bde
|
||||
// commit_url: https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d
|
||||
// cve: CVE-2017-16034
|
||||
// license: MIT
|
||||
// function: ps
|
||||
// relpath: lib/stats.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 1
|
||||
|
||||
var os = require('os')
|
||||
var fs = require('fs')
|
||||
var p = require('path')
|
||||
var exec = require('child_process').exec
|
||||
var spawn = require('child_process').spawn
|
||||
var helpers = require('./helpers')
|
||||
var format = require('util').format
|
||||
|
||||
var stats = {
|
||||
history: {},
|
||||
cpu: null, //used to store cpu informations
|
||||
proc: function(pid, options, done) {
|
||||
var self = this
|
||||
|
||||
if(this.cpu !== null) {
|
||||
fs.readFile('/proc/uptime', 'utf8', function(err, uptime) {
|
||||
if(err) {
|
||||
return done(err, null)
|
||||
}
|
||||
|
||||
if(uptime === undefined) {
|
||||
console.error("[pidusage] We couldn't find uptime from /proc/uptime")
|
||||
self.cpu.uptime = os.uptime()
|
||||
} else {
|
||||
self.cpu.uptime = uptime.split(' ')[0]
|
||||
}
|
||||
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
} else {
|
||||
helpers.cpu(function(err, cpu) {
|
||||
if(err) {
|
||||
return done(err, null)
|
||||
}
|
||||
|
||||
self.cpu = cpu
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
}
|
||||
},
|
||||
proc_calc: function(pid, options, done) {
|
||||
pid = parseInt(pid, 10)
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
var cpu = this.cpu
|
||||
var self = this
|
||||
|
||||
//Arguments to path.join must be strings
|
||||
fs.readFile(p.join('/proc', ''+pid, 'stat'), 'utf8', function(err, infos) {
|
||||
if(err) {
|
||||
return done(err, null)
|
||||
}
|
||||
|
||||
//https://github.com/arunoda/node-usage/commit/a6ca74ecb8dd452c3c00ed2bde93294d7bb75aa8
|
||||
//preventing process space in name by removing values before last ) (pid (name) ...)
|
||||
var index = infos.lastIndexOf(')')
|
||||
infos = infos.substr(index + 2).split(' ')
|
||||
|
||||
//according to http://man7.org/linux/man-pages/man5/proc.5.html (index 0 based - 2)
|
||||
//In kernels before Linux 2.6, start was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks
|
||||
var stat = {
|
||||
utime: parseFloat(infos[11]),
|
||||
stime: parseFloat(infos[12]),
|
||||
cutime: parseFloat(infos[13]),
|
||||
cstime: parseFloat(infos[14]),
|
||||
start: parseFloat(infos[19]) / cpu.clock_tick,
|
||||
rss: parseFloat(infos[21])
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/16726779/total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599
|
||||
|
||||
var childrens = options.childrens ? stat.cutime + stat.cstime : 0
|
||||
|
||||
var total = stat.stime - (history.stime || 0) + stat.utime - (history.utime || 0) + childrens
|
||||
|
||||
total = total / cpu.clock_tick
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? cpu.uptime - history.uptime : stat.start - cpu.uptime
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stat
|
||||
self.history[pid].uptime = cpu.uptime
|
||||
|
||||
return done(null, {
|
||||
cpu: (total / seconds) * 100,
|
||||
memory: stat.rss * cpu.pagesize
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Get pid informations through ps command
|
||||
* @param {int} pid
|
||||
* @return {Function} done (err, stat)
|
||||
* on os x skip headers with pcpu=,rss=
|
||||
* on linux it could be --no-header
|
||||
* on solaris 11 can't figure out a way to do this properly so...
|
||||
*/
|
||||
ps: function(pid, options, done) {
|
||||
pid = parseInt(pid, 10)
|
||||
var cmd = 'ps -o pcpu,rss -p '
|
||||
|
||||
if(os.platform() == 'aix')
|
||||
cmd = 'ps -o pcpu,rssize -p ' //this one could work on other platforms
|
||||
|
||||
exec(cmd + pid, function(err, stdout, stderr) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
stdout = stdout.split(os.EOL)[1]
|
||||
stdout = stdout.replace(/^\s+/, '').replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
return done(null, {
|
||||
cpu: parseFloat(stdout[0].replace(',', '.')),
|
||||
memory: parseFloat(stdout[1]) * 1024
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* This is really in a beta stage
|
||||
*/
|
||||
win: function(pid, options, done) {
|
||||
pid = parseInt(pid, 10)
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/469ec6b7-4727-4773-9dc7-6e3de40e87b8/cpu-usage-in-for-each-active-process-how-is-this-best-determined-and-implemented-in-an?forum=csharplanguage
|
||||
var args = 'PROCESS ' + pid + ' get workingsetsize,usermodetime,kernelmodetime'
|
||||
|
||||
var wmic = spawn('wmic', args.split(' '), {detached: true})
|
||||
var stdout = ''
|
||||
var stderr = ''
|
||||
var self = this
|
||||
var uptime = os.uptime()
|
||||
|
||||
wmic.stdout.on('data', function(d) {
|
||||
stdout += d.toString()
|
||||
})
|
||||
|
||||
wmic.stderr.on('data', function(d) {
|
||||
stderr += d.toString()
|
||||
})
|
||||
|
||||
wmic.on('error', function(err) {
|
||||
console.error('[pidusage] Command "wmic ' + args + '" failed with error %s', err)
|
||||
})
|
||||
|
||||
wmic.on('close', function(code) {
|
||||
stdout = stdout.trim()
|
||||
stderr = stderr.trim()
|
||||
|
||||
if(!stdout || code !== 0) {
|
||||
var error = format('%s Wmic errored, please open an issue on https://github.com/soyuka/pidusage with this message.%s', new Date().toString(), os.EOL)
|
||||
error += format('Command was "wmic %s" %s System informations: %s - release: %s %s - type %s %s', args, os.EOL, os.EOL, os.release(), os.EOL, os.type(), os.EOL)
|
||||
stderr = error + (stderr ? format('Wmic reported the following error: %s.', stderr) : 'Wmic reported no errors (stderr empty).')
|
||||
stderr = format('%s%s%sWmic exited with code %d.', os.EOL, stderr, os.EOL, code)
|
||||
stderr = format('%s%sStdout was %s', stderr, os.EOL, stdout ? stdout : 'empty')
|
||||
|
||||
return done(new Error(stderr, null))
|
||||
}
|
||||
|
||||
stdout = stdout.split(os.EOL)[1].replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
var stats = {
|
||||
kernelmodetime: parseFloat(stdout[0]),
|
||||
usermodetime: parseFloat(stdout[1]),
|
||||
}
|
||||
|
||||
var workingsetsize = parseFloat(stdout[2])
|
||||
|
||||
//process usage since last call
|
||||
var total = stats.kernelmodetime - (history.kernelmodetime || 0) + stats.usermodetime - (history.usermodetime || 0)
|
||||
total = total / 10000000
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? uptime - history.uptime : 0
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stats
|
||||
self.history[pid].uptime = uptime
|
||||
|
||||
return done(null, {cpu: (total / seconds) * 100, memory: workingsetsize})
|
||||
})
|
||||
wmic.stdin.end()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
// Provenance: soyuka/pidusage (vuln).
|
||||
// repo: soyuka/pidusage
|
||||
// commit: e3660d8a8e5e61afad9b02af67356a1e239d6bde
|
||||
// parent: e3660d8a8e5e61afad9b02af67356a1e239d6bde
|
||||
// commit_url: https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d
|
||||
// cve: CVE-2017-16034
|
||||
// license: MIT
|
||||
// function: ps
|
||||
// relpath: lib/stats.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 1
|
||||
|
||||
var os = require('os')
|
||||
var fs = require('fs')
|
||||
var p = require('path')
|
||||
var exec = require('child_process').exec
|
||||
var spawn = require('child_process').spawn
|
||||
var helpers = require('./helpers')
|
||||
var format = require('util').format
|
||||
|
||||
var stats = {
|
||||
history: {},
|
||||
cpu: null, //used to store cpu informations
|
||||
proc: function(pid, options, done) {
|
||||
var self = this
|
||||
|
||||
if(this.cpu !== null) {
|
||||
fs.readFile('/proc/uptime', 'utf8', function(err, uptime) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
if(uptime === undefined) {
|
||||
console.error("[pidusage] We couldn't find uptime from /proc/uptime")
|
||||
self.cpu.uptime = os.uptime()
|
||||
} else {
|
||||
self.cpu.uptime = uptime.split(' ')[0]
|
||||
}
|
||||
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
} else {
|
||||
helpers.cpu(function(err, cpu) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
self.cpu = cpu
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
}
|
||||
},
|
||||
proc_calc: function(pid, options, done) {
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
var cpu = this.cpu
|
||||
var self = this
|
||||
|
||||
//Arguments to path.join must be strings
|
||||
fs.readFile(p.join('/proc', ''+pid, 'stat'), 'utf8', function(err, infos) {
|
||||
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
//https://github.com/arunoda/node-usage/commit/a6ca74ecb8dd452c3c00ed2bde93294d7bb75aa8
|
||||
//preventing process space in name by removing values before last ) (pid (name) ...)
|
||||
var index = infos.lastIndexOf(')')
|
||||
infos = infos.substr(index + 2).split(' ')
|
||||
|
||||
//according to http://man7.org/linux/man-pages/man5/proc.5.html (index 0 based - 2)
|
||||
//In kernels before Linux 2.6, start was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks
|
||||
var stat = {
|
||||
utime: parseFloat(infos[11]),
|
||||
stime: parseFloat(infos[12]),
|
||||
cutime: parseFloat(infos[13]),
|
||||
cstime: parseFloat(infos[14]),
|
||||
start: parseFloat(infos[19]) / cpu.clock_tick,
|
||||
rss: parseFloat(infos[21])
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/16726779/total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599
|
||||
|
||||
var childrens = options.childrens ? stat.cutime + stat.cstime : 0
|
||||
|
||||
var total = stat.stime - (history.stime || 0) + stat.utime - (history.utime || 0) + childrens
|
||||
|
||||
total = total / cpu.clock_tick
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? cpu.uptime - history.uptime : stat.start - cpu.uptime
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stat
|
||||
self.history[pid].uptime = cpu.uptime
|
||||
|
||||
return done(null, {
|
||||
cpu: (total / seconds) * 100,
|
||||
memory: stat.rss * cpu.pagesize
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Get pid informations through ps command
|
||||
* @param {int} pid
|
||||
* @return {Function} done (err, stat)
|
||||
* on os x skip headers with pcpu=,rss=
|
||||
* on linux it could be --no-header
|
||||
* on solaris 11 can't figure out a way to do this properly so...
|
||||
*/
|
||||
ps: function(pid, options, done) {
|
||||
|
||||
var cmd = 'ps -o pcpu,rss -p '
|
||||
|
||||
if(os.platform() == 'aix')
|
||||
cmd = 'ps -o pcpu,rssize -p ' //this one could work on other platforms
|
||||
|
||||
exec(cmd + pid, function(err, stdout, stderr) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
stdout = stdout.split(os.EOL)[1]
|
||||
stdout = stdout.replace(/^\s+/, '').replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
return done(null, {
|
||||
cpu: parseFloat(stdout[0].replace(',', '.')),
|
||||
memory: parseFloat(stdout[1]) * 1024
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* This is really in a beta stage
|
||||
*/
|
||||
win: function(pid, options, done) {
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/469ec6b7-4727-4773-9dc7-6e3de40e87b8/cpu-usage-in-for-each-active-process-how-is-this-best-determined-and-implemented-in-an?forum=csharplanguage
|
||||
var args = 'PROCESS ' + pid + ' get workingsetsize,usermodetime,kernelmodetime'
|
||||
|
||||
var wmic = spawn('wmic', args.split(' '), {detached: true})
|
||||
var stdout = ''
|
||||
var stderr = ''
|
||||
var self = this
|
||||
var uptime = os.uptime()
|
||||
|
||||
wmic.stdout.on('data', function(d) {
|
||||
stdout += d.toString()
|
||||
})
|
||||
|
||||
wmic.stderr.on('data', function(d) {
|
||||
stderr += d.toString()
|
||||
})
|
||||
|
||||
wmic.on('error', function(err) {
|
||||
console.error('[pidusage] Command "wmic ' + args + '" failed with error %s', err)
|
||||
})
|
||||
|
||||
wmic.on('close', function(code) {
|
||||
stdout = stdout.trim()
|
||||
stderr = stderr.trim()
|
||||
|
||||
if(!stdout || code !== 0) {
|
||||
var error = format('%s Wmic errored, please open an issue on https://github.com/soyuka/pidusage with this message.%s', new Date().toString(), os.EOL)
|
||||
error += format('Command was "wmic %s" %s System informations: %s - release: %s %s - type %s %s', args, os.EOL, os.EOL, os.release(), os.EOL, os.type(), os.EOL)
|
||||
stderr = error + (stderr ? format('Wmic reported the following error: %s.', stderr) : 'Wmic reported no errors (stderr empty).')
|
||||
stderr = format('%s%s%sWmic exited with code %d.', os.EOL, stderr, os.EOL, code)
|
||||
stderr = format('%s%sStdout was %s', stderr, os.EOL, stdout ? stdout : 'empty')
|
||||
|
||||
return done(new Error(stderr, null))
|
||||
}
|
||||
|
||||
stdout = stdout.split(os.EOL)[1].replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
var stats = {
|
||||
kernelmodetime: parseFloat(stdout[0]),
|
||||
usermodetime: parseFloat(stdout[1]),
|
||||
}
|
||||
|
||||
var workingsetsize = parseFloat(stdout[2])
|
||||
|
||||
//process usage since last call
|
||||
var total = stats.kernelmodetime - (history.kernelmodetime || 0) + stats.usermodetime - (history.usermodetime || 0)
|
||||
total = total / 10000000
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? uptime - history.uptime : 0
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stats
|
||||
self.history[pid].uptime = uptime
|
||||
|
||||
return done(null, {cpu: (total / seconds) * 100, memory: workingsetsize})
|
||||
})
|
||||
wmic.stdin.end()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Provenance: rrainn/PortProcesses (fixed).
|
||||
// repo: rrainn/PortProcesses
|
||||
// commit: 86811216c9b97b01b5722f879f8c88a7aa4214e1
|
||||
// parent: fffceb09aff7180afbd0bd172e820404b33c8299
|
||||
// commit_url: https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1
|
||||
// cve: CVE-2021-23348
|
||||
// license: MIT
|
||||
// function: listProcessesOnPort
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 2
|
||||
|
||||
const listProcessesOnPort = module.exports.listProcessesOnPort = async port => {
|
||||
const portNumber = parseInt(port, 10);
|
||||
if (Number.isNaN(portNumber)) {
|
||||
console.error("Must provide number for port.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = (await exec(`lsof -i :${portNumber}`)).output.split('\n');
|
||||
const headers = result.shift().split(' ').filter(item => !!item.trim() && item.trim() !== "").map(item => item.toLowerCase());
|
||||
return result.filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue) => {
|
||||
accumulator.push(currentValue.split(' ').filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue, index) => {
|
||||
if (index > headers.length - 1) {
|
||||
accumulator[headers[headers.length - 1]] = (!!accumulator[headers[headers.length - 1]].trim() && accumulator[headers[headers.length - 1]].trim() !== "") ? `${accumulator[headers[headers.length - 1]]} ${currentValue}` : currentValue;
|
||||
} else {
|
||||
accumulator[headers[index]] = currentValue;
|
||||
}
|
||||
return accumulator;
|
||||
}, {}));
|
||||
return accumulator;
|
||||
}, []);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// Provenance: rrainn/PortProcesses (vuln).
|
||||
// repo: rrainn/PortProcesses
|
||||
// commit: fffceb09aff7180afbd0bd172e820404b33c8299
|
||||
// parent: fffceb09aff7180afbd0bd172e820404b33c8299
|
||||
// commit_url: https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1
|
||||
// cve: CVE-2021-23348
|
||||
// license: MIT
|
||||
// function: listProcessesOnPort
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 2
|
||||
|
||||
const listProcessesOnPort = module.exports.listProcessesOnPort = async port => {
|
||||
try {
|
||||
const result = (await exec(`lsof -i :${port}`)).output.split('\n');
|
||||
const headers = result.shift().split(' ').filter(item => !!item.trim() && item.trim() !== "").map(item => item.toLowerCase());
|
||||
return result.filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue) => {
|
||||
accumulator.push(currentValue.split(' ').filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue, index) => {
|
||||
if (index > headers.length - 1) {
|
||||
accumulator[headers[headers.length - 1]] = (!!accumulator[headers[headers.length - 1]].trim() && accumulator[headers[headers.length - 1]].trim() !== "") ? `${accumulator[headers[headers.length - 1]]} ${currentValue}` : currentValue;
|
||||
} else {
|
||||
accumulator[headers[index]] = currentValue;
|
||||
}
|
||||
return accumulator;
|
||||
}, {}));
|
||||
return accumulator;
|
||||
}, []);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,602 @@
|
||||
# vfc-js harvest recipes derived from SecBench.js fixCommit metadata by build_recipes.py.
|
||||
# Excerpts come from the upstream package repository (its license), never from SecBench.js.
|
||||
|
||||
[[recipe]]
|
||||
name = "angular-http-server-1-0-0"
|
||||
host = "github"
|
||||
repo = "simonh1000/angular-http-server"
|
||||
parent = "d171a771a92e4685b24fb77cb894a7b7b8024c5c"
|
||||
commit = "8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
path = "angular-http-server.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "angular-http-server.js"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2018
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "angular-http-server"
|
||||
sink_location = "angular-http-server.js:16:29"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink angular-http-server.js:16:29 fixed upstream in 8bafc9577161"
|
||||
commit_url = "https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "apex-publish-static-files-2-0-0"
|
||||
host = "github"
|
||||
repo = "vincentmorneau/apex-publish-static-files"
|
||||
parent = "8d28fe8a9a49e5ff3f61e239293b5646528e2915"
|
||||
commit = "2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-16462"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "apex-publish-static-files"
|
||||
sink_location = "index.js:54:25"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:54:25 fixed upstream in 2209af8f2b65"
|
||||
commit_url = "https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "arpping-2-0-0"
|
||||
host = "github"
|
||||
repo = "haf-decent/arpping"
|
||||
parent = "ce9efe8ab7f059ddf45ae4f8f7587689ac3c068c"
|
||||
commit = "0db06723f8c3c73a5cc0829c667d45cba25ca44d"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2021
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "arpping"
|
||||
sink_location = "index.js:120:13"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:120:13 fixed upstream in 0db06723f8c3"
|
||||
commit_url = "https://github.com/haf-decent/arpping/commit/0db06723f8c3c73a5cc0829c667d45cba25ca44d"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "bestzip-2-1-6"
|
||||
host = "github"
|
||||
repo = "nfriedly/node-bestzip"
|
||||
parent = "fcea252e52b6078eff6caf5531bd32c53fccb59f"
|
||||
commit = "45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
path = "lib/bestzip.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/bestzip.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7730"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "bestzip"
|
||||
sink_location = "lib/bestzip.js:27:27"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/bestzip.js:27:27 fixed upstream in 45d4a901478c"
|
||||
commit_url = "https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "clamscan-1-2-0"
|
||||
host = "github"
|
||||
repo = "kylefarris/clamscan"
|
||||
parent = "d474da7b89c0d3397cd681e79c7bcc592bff144b"
|
||||
commit = "5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7613"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "clamscan"
|
||||
sink_location = "index.js:495:36"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:495:36 fixed upstream in 5f557c970817"
|
||||
commit_url = "https://github.com/kylefarris/clamscan/commit/5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "codecov-3-6-4"
|
||||
host = "github"
|
||||
repo = "codecov/codecov-node"
|
||||
parent = "5f6cc62d4f83bf3a75c973868259798814cd231e"
|
||||
commit = "c0711c656686e902af2cd92d6aecc8074de4d83d"
|
||||
path = "lib/codecov.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/codecov.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-15123"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "codecov"
|
||||
sink_location = "lib/codecov.js:419:7"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/codecov.js:419:7 fixed upstream in c0711c656686"
|
||||
commit_url = "https://github.com/codecov/codecov-node/commit/c0711c656686e902af2cd92d6aecc8074de4d83d"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "crud-file-server-0-7-0"
|
||||
host = "github"
|
||||
repo = "omphalos/crud-file-server"
|
||||
parent = "833e7fcc2bc8406b9c76836a51ae173f50c56bf0"
|
||||
commit = "4fc3b404f718abb789f4ce4272c39c7a138c7a82"
|
||||
path = "crud-file-server.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "crud-file-server.js"
|
||||
license = "Unlicense"
|
||||
cve = "CVE-2018-3733"
|
||||
year = 2018
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "crud-file-server"
|
||||
sink_location = "crud-file-server.js:170:14"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink crud-file-server.js:170:14 fixed upstream in 4fc3b404f718"
|
||||
commit_url = "https://github.com/omphalos/crud-file-server/commit/4fc3b404f718abb789f4ce4272c39c7a138c7a82"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "diskusage-ng-0-2-6"
|
||||
host = "github"
|
||||
repo = "iximiuz/node-diskusage-ng"
|
||||
parent = "53c505506553c83861d1bd67823d6a382d3a5a43"
|
||||
commit = "48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
path = "lib/posix.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/posix.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7631"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "diskusage-ng"
|
||||
sink_location = "lib/posix.js:11:5"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/posix.js:11:5 fixed upstream in 48e7e093486b"
|
||||
commit_url = "https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "dns-sync-0-1-0"
|
||||
host = "github"
|
||||
repo = "skoranga/node-dns-sync"
|
||||
parent = "b748fe77a87749d95876028eda8e759109be4c73"
|
||||
commit = "d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
path = "lib/dns-sync.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/dns-sync.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2014-9682"
|
||||
year = 2014
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "dns-sync"
|
||||
sink_location = "lib/dns-sync.js:21:26"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/dns-sync.js:21:26 fixed upstream in d9abaae384b1"
|
||||
commit_url = "https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "get-npm-package-version-1-0-6"
|
||||
host = "github"
|
||||
repo = "hoperyy/get-npm-package-version"
|
||||
parent = "52797864df09049ea28d65d14620774257a965b0"
|
||||
commit = "40b1cf31a0607ea66f9e30a0c3af1383b52b2dec"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "ISC"
|
||||
cve = "CVE-2020-7795"
|
||||
year = 2021
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "get-npm-package-version"
|
||||
sink_location = "index.js:16:48"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:16:48 fixed upstream in 40b1cf31a060"
|
||||
commit_url = "https://github.com/hoperyy/get-npm-package-version/commit/40b1cf31a0607ea66f9e30a0c3af1383b52b2dec"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "glance-3-0-0"
|
||||
host = "github"
|
||||
repo = "jarofghosts/glance"
|
||||
parent = "7e69a5539236386e747fb240ae87ea65ed64bb2c"
|
||||
commit = "8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-3715"
|
||||
year = 2018
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "glance"
|
||||
sink_location = "index.js:81:14"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink index.js:81:14 fixed upstream in 8cfd88e44ebd"
|
||||
commit_url = "https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "hostr-2-0-0"
|
||||
host = "github"
|
||||
repo = "henrytseng/hostr"
|
||||
parent = "5827ba48fd4a08c26604b97798c57d45fe1cd51e"
|
||||
commit = "789a00047459fd80b6f0a9701a1378a47fb73ba8"
|
||||
path = "lib/routes/statics.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/routes/statics.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2017-16029"
|
||||
year = 2016
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "hostr"
|
||||
sink_location = "lib/routes/static.js:56:27"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink lib/routes/static.js:56:27 fixed upstream in 789a00047459"
|
||||
commit_url = "https://github.com/henrytseng/hostr/commit/789a00047459fd80b6f0a9701a1378a47fb73ba8"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "hot-formula-parser-3-0-0"
|
||||
host = "github"
|
||||
repo = "handsontable/formula-parser"
|
||||
parent = "944136096f44ff4ffd4ba0bcef30970ca4702fce"
|
||||
commit = "396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
path = "src/grammar-parser/grammar-parser.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "src/grammar-parser/grammar-parser.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-6836"
|
||||
year = 2019
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "hot-formula-parser"
|
||||
sink_location = "lib/grammar-parser/grammar-parser.js:258:31"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/grammar-parser/grammar-parser.js:258:31 fixed upstream in 396b089738d4"
|
||||
commit_url = "https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "is-my-json-valid-2-20-0"
|
||||
host = "github"
|
||||
repo = "mafintosh/is-my-json-valid"
|
||||
parent = "adf40bd9f22f6c9ee7d4c612c4193a7b835416bc"
|
||||
commit = "3419563687df463b4ca709a2b46be8e15d6a2b3d"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2020
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "is-my-json-valid"
|
||||
sink_location = "index.js:172:21"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink index.js:172:21 fixed upstream in 3419563687df"
|
||||
commit_url = "https://github.com/mafintosh/is-my-json-valid/commit/3419563687df463b4ca709a2b46be8e15d6a2b3d"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "libnmap-0-4-11"
|
||||
host = "github"
|
||||
repo = "jas-/node-libnmap"
|
||||
parent = "49b72239b144ab7ffdf673b62e18bfd0760948f6"
|
||||
commit = "c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
path = "lib/classes/tools.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/classes/tools.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-16461"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "libnmap"
|
||||
sink_location = "lib/classes/tools.js:114:25"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/classes/tools.js:114:25 fixed upstream in c235b24b0342"
|
||||
commit_url = "https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "node-simple-router-0-10-0"
|
||||
host = "github"
|
||||
repo = "sandy98/node-simple-router"
|
||||
parent = "91da4299aee0086cc1e0cc837763578af6f82cea"
|
||||
commit = "dfdd52e2e80607af433097d940b3834fd96df488"
|
||||
path = "lib/router.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/router.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2017-16083"
|
||||
year = 2017
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "node-simple-router"
|
||||
sink_location = "lib/router.js:757:27"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink lib/router.js:757:27 fixed upstream in dfdd52e2e806"
|
||||
commit_url = "https://github.com/sandy98/node-simple-router/commit/dfdd52e2e80607af433097d940b3834fd96df488"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "pdf-image-1-0-5"
|
||||
host = "github"
|
||||
repo = "roest01/node-pdf-image"
|
||||
parent = "d8c0dcadd93985dbefe80b84060f5f572bfbb6ff"
|
||||
commit = "54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-3757"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "pdf-image"
|
||||
sink_location = "index.js:43:7"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:43:7 fixed upstream in 54679496a897"
|
||||
commit_url = "https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "pidusage-1-0-0"
|
||||
host = "github"
|
||||
repo = "soyuka/pidusage"
|
||||
parent = "e3660d8a8e5e61afad9b02af67356a1e239d6bde"
|
||||
commit = "b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
path = "lib/stats.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/stats.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2017-16034"
|
||||
year = 2017
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "pidusage"
|
||||
sink_location = "lib/stats.js:108:5"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/stats.js:108:5 fixed upstream in b70eca15f7ca"
|
||||
commit_url = "https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "portprocesses-1-0-4"
|
||||
host = "github"
|
||||
repo = "rrainn/PortProcesses"
|
||||
parent = "fffceb09aff7180afbd0bd172e820404b33c8299"
|
||||
commit = "86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2021-23348"
|
||||
year = 2021
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "portprocesses"
|
||||
sink_location = "exec.js:5:3"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink exec.js:5:3 fixed upstream in 86811216c9b9"
|
||||
commit_url = "https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "serve-here-js-1-1-0"
|
||||
host = "github"
|
||||
repo = "ChristoPy/serve-here.js"
|
||||
parent = "ad077637bf7a9fe0dee3262f011aed19a45ce92c"
|
||||
commit = "cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
path = "source/response.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "source/response.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2019-5444"
|
||||
year = 2019
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "serve-here.js"
|
||||
sink_location = "source/server.js:27:15"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink source/server.js:27:15 fixed upstream in cefb51d03290"
|
||||
commit_url = "https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "static-eval-1-1-1"
|
||||
host = "github"
|
||||
repo = "browserify/static-eval"
|
||||
parent = "5bba7905b0e797460b8f6c2e38ff6869146faab3"
|
||||
commit = "32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2019
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "static-eval"
|
||||
sink_location = "index.js:118:20"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink index.js:118:20 fixed upstream in 32f8efd07262"
|
||||
commit_url = "https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "thenify-3-3-0"
|
||||
host = "github"
|
||||
repo = "thenables/thenify"
|
||||
parent = "aa21cfb64f47238c764d258d0faf7366a8487e36"
|
||||
commit = "0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7677"
|
||||
year = 2020
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "thenify"
|
||||
sink_location = "index.js:17:10"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink index.js:17:10 fixed upstream in 0d94a24eb933"
|
||||
commit_url = "https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "underscore-1-13-0-0"
|
||||
host = "github"
|
||||
repo = "jashkenas/underscore"
|
||||
parent = "ef646ccbbbd971e82719c83fc69f56a5585b3a01"
|
||||
commit = "4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
path = "modules/template.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "modules/template.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2021-23358"
|
||||
year = 2021
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "underscore"
|
||||
sink_location = "modules/template.js:71:14"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink modules/template.js:71:14 fixed upstream in 4c73526d4383"
|
||||
commit_url = "https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "whereis-0-4-0"
|
||||
host = "github"
|
||||
repo = "vvo/node-whereis"
|
||||
parent = "b8b642b1163baa37f15ed49b4064dcbdb6e1876c"
|
||||
commit = "0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-3772"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "whereis"
|
||||
sink_location = "index.js:4:6"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:4:6 fixed upstream in 0f64e3780235"
|
||||
commit_url = "https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
split = "holdout"
|
||||
@@ -0,0 +1,29 @@
|
||||
// Provenance: ChristoPy/serve-here.js (fixed).
|
||||
// repo: ChristoPy/serve-here.js
|
||||
// commit: cefb51d03290b6a88dd13143ab2de31b8cf57c39
|
||||
// parent: ad077637bf7a9fe0dee3262f011aed19a45ce92c
|
||||
// commit_url: https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39
|
||||
// cve: CVE-2019-5444
|
||||
// license: MIT
|
||||
// function: ConfigureFilePath
|
||||
// relpath: source/response.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 14
|
||||
|
||||
module.exports.ConfigureFilePath = (Options, FilePath) => {
|
||||
|
||||
const Slash = FilePath.split ("")[FilePath.split ("").length - 1] === "/";
|
||||
|
||||
if (FilePath === "/") {
|
||||
return `${Options.RootFolder}/${Options.IndexFile}`;
|
||||
} else {
|
||||
const IsMalicious = HasMaliciousPath(Options, FilePath);
|
||||
|
||||
if (IsMalicious) {
|
||||
return null;
|
||||
} else {
|
||||
return (Slash ? `${Options.RootFolder}${FilePath.slice (0, -1)}` : `${Options.RootFolder}${FilePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Provenance: ChristoPy/serve-here.js (vuln).
|
||||
// repo: ChristoPy/serve-here.js
|
||||
// commit: ad077637bf7a9fe0dee3262f011aed19a45ce92c
|
||||
// parent: ad077637bf7a9fe0dee3262f011aed19a45ce92c
|
||||
// commit_url: https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39
|
||||
// cve: CVE-2019-5444
|
||||
// license: MIT
|
||||
// function: ConfigureFilePath
|
||||
// relpath: source/response.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 5
|
||||
|
||||
module.exports.ConfigureFilePath = (Options, FilePath) => {
|
||||
|
||||
const Slash = FilePath.split ("")[FilePath.split ("").length - 1] === "/";
|
||||
|
||||
switch (FilePath) {
|
||||
|
||||
case "/": return `${Options.RootFolder}/${Options.IndexFile}`;
|
||||
default: return (Slash ? `${Options.RootFolder}${FilePath.slice (0, -1)}` : `${Options.RootFolder}${FilePath}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
// Provenance: browserify/static-eval (fixed).
|
||||
// repo: browserify/static-eval
|
||||
// commit: 32f8efd072625e267aa7237d2daff35738c50d2a
|
||||
// parent: 5bba7905b0e797460b8f6c2e38ff6869146faab3
|
||||
// commit_url: https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: walk
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 3
|
||||
|
||||
module.exports = function (ast, vars) {
|
||||
if (!vars) vars = {};
|
||||
var FAIL = {};
|
||||
|
||||
var result = (function walk (node, scopeVars) {
|
||||
if (node.type === 'Literal') {
|
||||
return node.value;
|
||||
}
|
||||
else if (node.type === 'UnaryExpression'){
|
||||
var val = walk(node.argument)
|
||||
if (node.operator === '+') return +val
|
||||
if (node.operator === '-') return -val
|
||||
if (node.operator === '~') return ~val
|
||||
if (node.operator === '!') return !val
|
||||
return FAIL
|
||||
}
|
||||
else if (node.type === 'ArrayExpression') {
|
||||
var xs = [];
|
||||
for (var i = 0, l = node.elements.length; i < l; i++) {
|
||||
var x = walk(node.elements[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
xs.push(x);
|
||||
}
|
||||
return xs;
|
||||
}
|
||||
else if (node.type === 'ObjectExpression') {
|
||||
var obj = {};
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i];
|
||||
var value = prop.value === null
|
||||
? prop.value
|
||||
: walk(prop.value)
|
||||
;
|
||||
if (value === FAIL) return FAIL;
|
||||
obj[prop.key.value || prop.key.name] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
else if (node.type === 'BinaryExpression' ||
|
||||
node.type === 'LogicalExpression') {
|
||||
var l = walk(node.left);
|
||||
if (l === FAIL) return FAIL;
|
||||
var r = walk(node.right);
|
||||
if (r === FAIL) return FAIL;
|
||||
|
||||
var op = node.operator;
|
||||
if (op === '==') return l == r;
|
||||
if (op === '===') return l === r;
|
||||
if (op === '!=') return l != r;
|
||||
if (op === '!==') return l !== r;
|
||||
if (op === '+') return l + r;
|
||||
if (op === '-') return l - r;
|
||||
if (op === '*') return l * r;
|
||||
if (op === '/') return l / r;
|
||||
if (op === '%') return l % r;
|
||||
if (op === '<') return l < r;
|
||||
if (op === '<=') return l <= r;
|
||||
if (op === '>') return l > r;
|
||||
if (op === '>=') return l >= r;
|
||||
if (op === '|') return l | r;
|
||||
if (op === '&') return l & r;
|
||||
if (op === '^') return l ^ r;
|
||||
if (op === '&&') return l && r;
|
||||
if (op === '||') return l || r;
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
else if (node.type === 'Identifier') {
|
||||
if ({}.hasOwnProperty.call(vars, node.name)) {
|
||||
return vars[node.name];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'ThisExpression') {
|
||||
if ({}.hasOwnProperty.call(vars, 'this')) {
|
||||
return vars['this'];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'CallExpression') {
|
||||
var callee = walk(node.callee);
|
||||
if (callee === FAIL) return FAIL;
|
||||
if (typeof callee !== 'function') return FAIL;
|
||||
|
||||
var ctx = node.callee.object ? walk(node.callee.object) : FAIL;
|
||||
if (ctx === FAIL) ctx = null;
|
||||
|
||||
var args = [];
|
||||
for (var i = 0, l = node.arguments.length; i < l; i++) {
|
||||
var x = walk(node.arguments[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
args.push(x);
|
||||
}
|
||||
return callee.apply(ctx, args);
|
||||
}
|
||||
else if (node.type === 'MemberExpression') {
|
||||
var obj = walk(node.object);
|
||||
// do not allow access to methods on Function
|
||||
if((obj === FAIL) || (typeof obj == 'function')){
|
||||
return FAIL;
|
||||
}
|
||||
if (node.property.type === 'Identifier') {
|
||||
return obj[node.property.name];
|
||||
}
|
||||
var prop = walk(node.property);
|
||||
if (prop === FAIL) return FAIL;
|
||||
return obj[prop];
|
||||
}
|
||||
else if (node.type === 'ConditionalExpression') {
|
||||
var val = walk(node.test)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val ? walk(node.consequent) : walk(node.alternate)
|
||||
}
|
||||
else if (node.type === 'ExpressionStatement') {
|
||||
var val = walk(node.expression)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val;
|
||||
}
|
||||
else if (node.type === 'ReturnStatement') {
|
||||
return walk(node.argument)
|
||||
}
|
||||
else if (node.type === 'FunctionExpression') {
|
||||
|
||||
var bodies = node.body.body;
|
||||
|
||||
// Create a "scope" for our arguments
|
||||
var oldVars = {};
|
||||
Object.keys(vars).forEach(function(element){
|
||||
oldVars[element] = vars[element];
|
||||
})
|
||||
|
||||
node.params.forEach(function(key) {
|
||||
if(key.type == 'Identifier'){
|
||||
vars[key.name] = null;
|
||||
}
|
||||
else return FAIL;
|
||||
});
|
||||
for(var i in bodies){
|
||||
if(walk(bodies[i]) === FAIL){
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
// restore the vars and scope after we walk
|
||||
vars = oldVars;
|
||||
|
||||
var keys = Object.keys(vars);
|
||||
var vals = keys.map(function(key) {
|
||||
return vars[key];
|
||||
});
|
||||
return Function(keys.join(', '), 'return ' + unparse(node)).apply(null, vals);
|
||||
}
|
||||
else if (node.type === 'TemplateLiteral') {
|
||||
var str = '';
|
||||
for (var i = 0; i < node.expressions.length; i++) {
|
||||
str += walk(node.quasis[i]);
|
||||
str += walk(node.expressions[i]);
|
||||
}
|
||||
str += walk(node.quasis[i]);
|
||||
return str;
|
||||
}
|
||||
else if (node.type === 'TaggedTemplateExpression') {
|
||||
var tag = walk(node.tag);
|
||||
var quasi = node.quasi;
|
||||
var strings = quasi.quasis.map(walk);
|
||||
var values = quasi.expressions.map(walk);
|
||||
return tag.apply(null, [strings].concat(values));
|
||||
}
|
||||
else if (node.type === 'TemplateElement') {
|
||||
return node.value.cooked;
|
||||
}
|
||||
else return FAIL;
|
||||
})(ast);
|
||||
|
||||
return result === FAIL ? undefined : result;
|
||||
};
|
||||
@@ -0,0 +1,187 @@
|
||||
// Provenance: browserify/static-eval (vuln).
|
||||
// repo: browserify/static-eval
|
||||
// commit: 5bba7905b0e797460b8f6c2e38ff6869146faab3
|
||||
// parent: 5bba7905b0e797460b8f6c2e38ff6869146faab3
|
||||
// commit_url: https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: walk
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 3
|
||||
|
||||
module.exports = function (ast, vars) {
|
||||
if (!vars) vars = {};
|
||||
var FAIL = {};
|
||||
|
||||
var result = (function walk (node, scopeVars) {
|
||||
if (node.type === 'Literal') {
|
||||
return node.value;
|
||||
}
|
||||
else if (node.type === 'UnaryExpression'){
|
||||
var val = walk(node.argument)
|
||||
if (node.operator === '+') return +val
|
||||
if (node.operator === '-') return -val
|
||||
if (node.operator === '~') return ~val
|
||||
if (node.operator === '!') return !val
|
||||
return FAIL
|
||||
}
|
||||
else if (node.type === 'ArrayExpression') {
|
||||
var xs = [];
|
||||
for (var i = 0, l = node.elements.length; i < l; i++) {
|
||||
var x = walk(node.elements[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
xs.push(x);
|
||||
}
|
||||
return xs;
|
||||
}
|
||||
else if (node.type === 'ObjectExpression') {
|
||||
var obj = {};
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i];
|
||||
var value = prop.value === null
|
||||
? prop.value
|
||||
: walk(prop.value)
|
||||
;
|
||||
if (value === FAIL) return FAIL;
|
||||
obj[prop.key.value || prop.key.name] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
else if (node.type === 'BinaryExpression' ||
|
||||
node.type === 'LogicalExpression') {
|
||||
var l = walk(node.left);
|
||||
if (l === FAIL) return FAIL;
|
||||
var r = walk(node.right);
|
||||
if (r === FAIL) return FAIL;
|
||||
|
||||
var op = node.operator;
|
||||
if (op === '==') return l == r;
|
||||
if (op === '===') return l === r;
|
||||
if (op === '!=') return l != r;
|
||||
if (op === '!==') return l !== r;
|
||||
if (op === '+') return l + r;
|
||||
if (op === '-') return l - r;
|
||||
if (op === '*') return l * r;
|
||||
if (op === '/') return l / r;
|
||||
if (op === '%') return l % r;
|
||||
if (op === '<') return l < r;
|
||||
if (op === '<=') return l <= r;
|
||||
if (op === '>') return l > r;
|
||||
if (op === '>=') return l >= r;
|
||||
if (op === '|') return l | r;
|
||||
if (op === '&') return l & r;
|
||||
if (op === '^') return l ^ r;
|
||||
if (op === '&&') return l && r;
|
||||
if (op === '||') return l || r;
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
else if (node.type === 'Identifier') {
|
||||
if ({}.hasOwnProperty.call(vars, node.name)) {
|
||||
return vars[node.name];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'ThisExpression') {
|
||||
if ({}.hasOwnProperty.call(vars, 'this')) {
|
||||
return vars['this'];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'CallExpression') {
|
||||
var callee = walk(node.callee);
|
||||
if (callee === FAIL) return FAIL;
|
||||
if (typeof callee !== 'function') return FAIL;
|
||||
|
||||
var ctx = node.callee.object ? walk(node.callee.object) : FAIL;
|
||||
if (ctx === FAIL) ctx = null;
|
||||
|
||||
var args = [];
|
||||
for (var i = 0, l = node.arguments.length; i < l; i++) {
|
||||
var x = walk(node.arguments[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
args.push(x);
|
||||
}
|
||||
return callee.apply(ctx, args);
|
||||
}
|
||||
else if (node.type === 'MemberExpression') {
|
||||
var obj = walk(node.object);
|
||||
// do not allow access to methods on Function
|
||||
if((obj === FAIL) || (typeof obj == 'function')){
|
||||
return FAIL;
|
||||
}
|
||||
if (node.property.type === 'Identifier') {
|
||||
return obj[node.property.name];
|
||||
}
|
||||
var prop = walk(node.property);
|
||||
if (prop === FAIL) return FAIL;
|
||||
return obj[prop];
|
||||
}
|
||||
else if (node.type === 'ConditionalExpression') {
|
||||
var val = walk(node.test)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val ? walk(node.consequent) : walk(node.alternate)
|
||||
}
|
||||
else if (node.type === 'ExpressionStatement') {
|
||||
var val = walk(node.expression)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val;
|
||||
}
|
||||
else if (node.type === 'ReturnStatement') {
|
||||
return walk(node.argument)
|
||||
}
|
||||
else if (node.type === 'FunctionExpression') {
|
||||
|
||||
var bodies = node.body.body;
|
||||
|
||||
// Create a "scope" for our arguments
|
||||
var oldVars = {};
|
||||
Object.keys(vars).forEach(function(element){
|
||||
oldVars[element] = vars[element];
|
||||
})
|
||||
|
||||
node.params.forEach(function(key) {
|
||||
if(key.type == 'Identifier'){
|
||||
vars[key.name] = null;
|
||||
}
|
||||
});
|
||||
for(var i in bodies){
|
||||
if(walk(bodies[i]) === FAIL){
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
// restore the vars and scope after we walk
|
||||
vars = oldVars;
|
||||
|
||||
var keys = Object.keys(vars);
|
||||
var vals = keys.map(function(key) {
|
||||
return vars[key];
|
||||
});
|
||||
return Function(keys.join(', '), 'return ' + unparse(node)).apply(null, vals);
|
||||
}
|
||||
else if (node.type === 'TemplateLiteral') {
|
||||
var str = '';
|
||||
for (var i = 0; i < node.expressions.length; i++) {
|
||||
str += walk(node.quasis[i]);
|
||||
str += walk(node.expressions[i]);
|
||||
}
|
||||
str += walk(node.quasis[i]);
|
||||
return str;
|
||||
}
|
||||
else if (node.type === 'TaggedTemplateExpression') {
|
||||
var tag = walk(node.tag);
|
||||
var quasi = node.quasi;
|
||||
var strings = quasi.quasis.map(walk);
|
||||
var values = quasi.expressions.map(walk);
|
||||
return tag.apply(null, [strings].concat(values));
|
||||
}
|
||||
else if (node.type === 'TemplateElement') {
|
||||
return node.value.cooked;
|
||||
}
|
||||
else return FAIL;
|
||||
})(ast);
|
||||
|
||||
return result === FAIL ? undefined : result;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user