Both tools scanned the same OWASP Juice Shop source, but they are doing fundamentally different jobs — so this is less "which is better" than "which question are you asking."
Audn is a whole-app adversarial assessment that fuses static analysis with a live red-team run against a deployed target. It maps the entire intentional vulnerability surface (103 findings) and — critically — reproduced 18 of them live. Use it to answer "what can actually be exploited on the running app, right now?"
Codex is a commit-diff code review. Nearly every one of its 20 findings is framed as "introduced by this commit" — it hunts unintended regressions, supply-chain/CI weaknesses, privacy leaks and subtle logic bugs, and ships a proposed patch per finding. Use it to answer "did this change introduce something that shouldn't be there?"
Bottom line: they are complementary, not redundant. Overlap is only 6 issue areas. Audn owns breadth + live proof of the app's real attack surface; Codex owns depth on the changeset and the whole class of build/CI/privacy/regression issues Audn's exploit-focused lens never looks at. Run both; neither alone covers the six shared blind spots (dependency CVEs, client-side depth, multi-step business logic, crypto depth, live infra posture, and unconfirmed-lead exploitability).
Same target (ozgurozkan123/juice-shop), two very different methodologies. The severity mixes below already tell the story: Audn reports across the full range and confirms a live-critical tier; Codex reports a tighter, mostly high/medium set of introduced issues.
160f306. Each finding has a validation rubric, evidence with file:line, and a generated patch. Focus: what the change introduced, plus a full threat model & criticality calibration.Audn's biggest structural advantage is that it grades its own certainty. Only 16 findings are corroborated by both static + live; another 63 are static-only leads the run never reached, and it explicitly labels 4 as likely false positives. This is what separates "facts about the running system" from "patterns in the source." Codex has no equivalent tier — all 20 are static, unverified against a live target.
Read this against your goal. If the goal is "prove exploitability and cover the app," Audn's column is the one that matters. If the goal is "gate a pull request and catch regressions/supply-chain," Codex's column is.
data JWTs accepted as bearer).image_actions.yml).| Dimension | Audn Vuln Finder | Codex Vuln Finder |
|---|---|---|
| Core method | Static analysis fused with a live red-team / DAST run | Static code review of a specific commit diff |
| Scope | Whole application, deployed instance | What the changeset introduced |
| Findings | 103 (18 Crit / 24 High / 52 Med / 5 Low / 4 Info) | 20 (8 High / 7 Med / 2 Low / 3 Info) |
| Live confirmation | 18 reproduced live; explicit confidence tiers | None — all static, unverified at runtime |
| Remediation | Prose guidance, CVSS, attack paths | Generated patch (git diff) per finding |
| Intentional vs unintended | Does not distinguish — ranks by severity/confidence | Explicitly separates challenge vulns from real risk |
| Sweet spot | Pentest / attack-surface mapping / exploitability proof | PR gate / regression & supply-chain review |
| Runtime cost | Heavy — 2h 28m, needs a live target | Light — static, diff-scoped |
| Blind to… | Build/CI, privacy, dependency CVEs, the diff | The 88 app-surface vulns it never looked for |
The taxonomies don't line up 1:1 (Audn uses CWE + file:line; Codex uses descriptive, diff-scoped titles), so overlap is mapped at the issue-area level. The headline: the two sets barely intersect.
Units differ by design: Audn counts individual findings (88 exclusive + 15 shared = 103); Codex's 20 findings collapse to ~14 distinct issues (9 exclusive + the rest across the 6 shared clusters). "6 shared areas" is the issue-level intersection.
Both flag that JWTs can be forged/altered. Audn traces the hard-coded RSA key and algorithm-confusion in lib/insecurity.ts as a pre-existing weakness; Codex flags a newly-introduced global registration of forged JWTs (app.use(updateAuthenticatedUsers())) that widens it to account takeover — plus 2FA temp-JWTs accepted as bearer.
Same file, same root cause: image_actions.yml runs mutable third-party actions (@main) with GITHUB_TOKEN. Audn rates it Medium (static lead); Codex rates it High and ships a pinning patch.
Both find shell-command injection from the release tag name in the news-update workflows. Audn flags both update-news-www.yml and the legacy variant; Codex focuses on the legacy workflow with a cross-repo bot token and a patch.
Both flag the npm/Docker build integrity gap. Audn: lockless installs (.npmrc), mutable base images and build-arg npm injection in the Dockerfile. Codex: deleted lockfiles + npm install in release/Docker paths and --ignore-scripts removed in CI.
Both hit the chatbot getOrderById authorization in routes/chat.ts. Audn: unverified JWT controls chat identity + lossy vowel-stripping email match collides identities. Codex: the order tool trusts an unsigned JWT payload as the authenticated identity.
Same two files (nftMint.ts, web3Wallet.ts) — different bug each. Audn: wallet ownership is never verified (authorization). Codex: lazy await import('ethers') races the isEventListenerCreated flag, creating duplicate listeners (resource exhaustion). A good illustration of how the two lenses complement each other.
These cluster into classes Audn's app-exploit lens structurally can't see: changeset regressions, supply-chain-of-recent-changes, privacy, DoS, AI/developer tooling, and code health.
A commit stopped inserting no-data JWTs into authenticatedUsers to avoid a crash, but those tokens are still not rejected — they flow through as valid bearer auth. A subtle regression an app-surface red-team wouldn't reach.
routes/2fa flow / insecurity.tsA per-request challenge check runs an unbounded ComplaintModel.findAll() plus an O(n) string-similarity loop over every complaint — a denial-of-service amplifier introduced by the changeset.
routes/verify.ts, models/complaint.tsA newly-added developer/AI-agent skill fetches arbitrary URLs with shell curl and feeds the response back to the agent — untrusted retrieval that can reach localhost/link-local/internal ranges. A supply-chain / agent-tooling surface Audn never scanned.
.junie/skills/add-reference/SKILL.mdThe new default "neon-fire" theme hard-codes remote Google Fonts (fonts.googleapis.com/gstatic.com), leaking every visitor's IP/UA/referer to a third party. A privacy/info-leak class Audn's exploit-focused lens ignores.
config/ctf.yml, index.htmlNew code passes a native Windows absolute glob to Unix-only basename parsing — breaks i18n file restore on Windows. A cross-platform robustness bug, invisible to a Linux live target.
lib/startup/restoreOverwrittenFilesWithOriginals.tsA display-name capitalization mismatch breaks an exact-match lookup, making the Exposed-Credentials guided tutorial unavailable. Non-security functional regression.
data/static/challenges.ymlTest-coverage regression: the spec no longer asserts that exactly 4096 chars is valid. Pure code-health finding.
complaint.component.spec.tsOptional metadata-file absence is no longer handled gracefully and throws a 500 instead of degrading. Robustness regression.
routes/vulnCodeSnippet.tsThe entire intentional-vulnerability surface of the app, including the live-confirmed criticals. Green counts = reproduced against the running target. Hover any chip for its CWE and location.
Cross-referenced against Juice Shop's own 113-challenge catalogue (16 categories). These are the shared blind spots — treat them as "do not assume covered," not "confirmed absent."
Neither enumerated actual CVEs in the intentionally-vulnerable npm packages. Audn treats them as noise; Codex explicitly deprioritizes "known vulnerable dependencies intentionally used." → Run a real SCA (npm audit / Snyk / OWASP Dependency-Check).
Both are server-code-centric. Angular DOM sinks beyond the few flagged, CSP weaknesses, client-side routing/auth, and stored-vs-reflected variants are under-explored. Only a handful of the 9 XSS challenges surfaced.
Many challenges require chaining (GDPR erasure flow, forged-coupon end-to-end, premium unlocks, "Christmas special"). Audn surfaces the component leads; few are demonstrated end-to-end. Codex is out of scope for these entirely.
Weak encryption of specific data, the nested easter-egg, backup decryption, and JWT issues beyond the flagged key/alg are only partially reached.
TLS config, security headers, container hardening and real-secret exposure on the actual Render instance weren't audited. Audn probed live but left 18 findings at "no verdict."
63 Audn static leads + 18 probed-no-verdict + all 20 Codex findings are unverified against a live target. Whether each is truly exploitable in your deployment is unknown until proven.
Where each tool put its attention. ●●● = strong (8+ findings), ●● = moderate (3–7), ● = light (1–2), — = none. This is the clearest picture of how little the two overlap: Audn owns the top of the OWASP surface; Codex concentrates in supply-chain, privacy and introduced logic bugs.
| Vulnerability class | Audn | Codex |
|---|---|---|
| SQL Injection | ●2 | —— |
| NoSQL Injection | ●●3 | —— |
| XSS | ●●6 | —— |
| XXE | ●1 | —— |
| SSRF | ●1 | ●2 |
| Path Traversal | ●●6 | —— |
| Code Injection / RCE | ●2 | ●1 |
| Broken Access Control / IDOR | ●●●16 | ●2 |
| JWT / Token Auth | ●●3 | ●2 |
| Auth Rate-Limiting | ●2 | —— |
| Weak Password Recovery | ●1 | —— |
| Weak Credentials/Hashing | ●2 | —— |
| Hardcoded Secrets/Creds | ●●●11 | —— |
| Sensitive Data Exposure | ●●●12 | ●2 |
| Open Redirect | ●1 | —— |
| CSRF | ●2 | —— |
| Broken Anti-Automation | ●2 | —— |
| Business Logic | ●2 | —— |
| Race Condition | ●●3 | ●2 |
| Improper Input Validation | ●●4 | ●2 |
| Cleartext Transmission | ●2 | —— |
| DoS / Resource Exhaustion | ●●3 | ●1 |
| Supply Chain / CI-CD | ●●●8 | ●●6 |
| Insufficient Verification | ●●3 | —— |
Counts are findings tagged to each class. Codex classes are aggregated from its 20 findings (including near-duplicate pairs). Classes with "—" for both are candidates for the unknown-unknowns list.
Every finding from both reports, filterable. Use this as the working index behind the analysis above.
| # | Sev | Finding | CWE | Location | Confidence | Overlap |
|---|---|---|---|---|---|---|
| #1 | Critical | CWE-532: Insertion of Sensitive Information into Log File LIVE | CWE-532 | server.ts:280 | Confirmed | Audn only |
| #2 | Critical | CWE-307 LIVE | CWE-307 | server.ts:340 | Confirmed | Audn only |
| #3 | Critical | CWE-521 LIVE | CWE-521 | frontend/src/app/oauth/oauth.component.ts:27 | Confirmed | Audn only |
| #4 | Critical | CWE-321 LIVE | CWE-321 | data/static/users.yml:259 | Confirmed | Audn only |
| #5 | Critical | CWE-798: Use of Hard-coded Credentials LIVE | CWE-798 | data/static/users.yml:167 | Confirmed | Audn only |
| #6 | Critical | CWE-798: Use of Hard-coded Credentials LIVE | CWE-798 | config/7ms.yml:143 | Confirmed | Audn only |
| #7 | Critical | CWE-640: Weak Password Recovery Mechanism for Forgotten Password LIVE | CWE-640 | routes/resetPassword.ts:18 | Confirmed | Audn only |
| #8 | Critical | CWE-798: Use of Hard-coded Credentials LIVE | CWE-798 | routes/login.ts:59 | Confirmed | Audn only |
| #9 | High | CWE-89: Improper Neutralization of Special Elements used in an SQL Command (SQL Injection) LIVE | CWE-89 | routes/search.ts:21 | Confirmed | Audn only |
| #10 | High | CWE-943 LIVE | CWE-943 | routes/trackOrder.ts:15 | Confirmed | Audn only |
| #11 | High | CWE-943 LIVE | CWE-943 | routes/showProductReviews.ts:31 | Confirmed | Audn only |
| #12 | High | CWE-916 LIVE | CWE-916 | models/user.ts:73 | Confirmed | Audn only |
| #13 | High | CWE-79: Improper Neutralization of Input During Web Page Generation (Cross-site Scripting) LIVE | CWE-79 | models/product.ts:42 | Confirmed | Audn only |
| #14 | High | CWE-200: Exposure of Sensitive Information to an Unauthorized Actor LIVE | CWE-200 | routes/memory.ts:22 | Confirmed | Audn only |
| #15 | High | CWE-307 LIVE | CWE-307 | routes/2fa.ts:16 | Confirmed | Audn only |
| #16 | High | CWE-200: Exposure of Sensitive Information to an Unauthorized Actor LIVE | CWE-200 | lib/challengeUtils.ts:52 | Confirmed | Audn only |
| #17 | Critical | Spoofable X-Forwarded-For header bypasses password-reset rate limit (account-takeover enabler) LIVE | | Observed | Audn only | |
| #18 | Critical | Unauthenticated public access logs contain change-password URLs with cleartext current/new passwords LIVE | | Observed | Audn only | |
| #19 | Critical | ZIP upload permits arbitrary application file overwrite | CWE-22 | routes/fileUpload.ts:27 | Probed | Audn only |
| #20 | Critical | Search query causes DOM-based XSS | CWE-79 | frontend/src/app/search-result/search-result.component.ts:135 | Probed | Audn only |
| #21 | Critical | Mutable base images enter production builds | CWE-829 | Dockerfile:1 | Probed | Both |
| #22 | Critical | Hardcoded JWT private key enables token forgery | CWE-321 | lib/insecurity.ts:20 | Probed | Both |
| #23 | Critical | Release tag enables cross-repository command injection | CWE-78 | .github/workflows/update-news-www.yml:18 | Probed | Both |
| #24 | Critical | Tracking ID enables reflected cross-site scripting | CWE-79 | frontend/src/app/track-result/track-result.component.ts:45 | Probed | Audn only |
| #25 | Critical | Build argument injects arbitrary npm packages | CWE-88 | Dockerfile:18 | Probed | Both |
| #26 | High | Anonymous XML upload discloses local files | CWE-611 | server.ts:307 | Probed | Audn only |
| #27 | High | Profile image URL enables SSRF | CWE-918 | server.ts:307 | Probed | Audn only |
| #28 | High | Unbounded upload can exhaust server disk | CWE-400 | server.ts:698 | Probed | Audn only |
| #29 | High | Backslashes bypass quarantine path validation | CWE-22 | routes/quarantineServer.ts:10 | Probed | Audn only |
| #30 | High | Order data enables remote code execution | CWE-94 | routes/b2bOrder.ts:19 | Probed | Audn only |
| #31 | High | Stored username enables server-side code execution | CWE-95 | routes/userProfile.ts:54 | Probed | Audn only |
| #32 | High | Remote installer executes without integrity verification | CWE-494 | .github/workflows/ci.yml:357 | Probed | Both |
| #33 | High | Remote SVG upload enables stored XSS | CWE-79 | server.ts:310 | Probed | Audn only |
| #34 | High | Lockless installs execute mutable dependency code | CWE-829 | .npmrc:1 | Probed | Both |
| #35 | High | JWT verification trusts attacker-selected algorithm | CWE-347 | lib/insecurity.ts:52 | Probed | Both |
| #36 | High | Release tag injects commands into legacy website update | CWE-78 | .github/workflows/update-news-www-legacy.yml:18 | Probed | Both |
| #37 | Critical | Login query permits authentication bypass | CWE-89 | routes/login.ts:32 | Static lead | Audn only |
| #38 | High | Null suffix bypass enables Windows file traversal | CWE-22 | routes/fileServer.ts:16 | Static lead | Audn only |
| #39 | High | Password change skips current-password verification | CWE-620 | routes/changePassword.ts:39 | Static lead | Audn only |
| #40 | High | Endpoint exposes complete runtime configuration | CWE-200 | routes/appConfiguration.ts:10 | Static lead | Audn only |
| #41 | High | Repository code executes with CI secrets | CWE-200 | .github/workflows/ci.yml:229 | Static lead | Audn only |
| #42 | High | Security answer bypass permits unverified erasure requests | CWE-620 | routes/dataErasure.ts:74 | Static lead | Audn only |
| #43 | Medium | Production error handler exposes stack traces | CWE-209 | server.ts:314 | Static lead | Audn only |
| #44 | Medium | Metrics endpoint is exposed without authentication | CWE-200 | server.ts:725 | Static lead | Audn only |
| #45 | Medium | Anonymous FTP directory listing exposes hidden files | CWE-548 | server.ts:267 | Static lead | Audn only |
| #46 | Medium | Anonymous users can modify products | CWE-862 | server.ts:368 | Static lead | Audn only |
| #47 | Medium | YAML aliases block the Node.js event loop | CWE-400 | routes/fileUpload.ts:101 | Static lead | Audn only |
| #48 | Medium | Substring allowlist permits arbitrary external redirects | CWE-601 | routes/redirect.ts:13 | Static lead | Audn only |
| #49 | Medium | Unbounded image download exhausts server storage | CWE-400 | routes/profileImageUrlUpload.ts:24 | Static lead | Audn only |
| #50 | Medium | Users can edit reviews owned by others | CWE-639 | routes/updateProductReviews.ts:16 | Static lead | Audn only |
| #51 | Medium | NoSQL selector updates every product review | CWE-943 | routes/updateProductReviews.ts:17 | Static lead | Audn only |
| #52 | Medium | Ordinary users can enumerate all user profiles | CWE-862 | routes/authenticatedUsers.ts:10 | Static lead | Audn only |
| #53 | Medium | Arbitrary field selection exposes credential material | CWE-200 | routes/currentUser.ts:20 | Static lead | Audn only |
| #54 | Medium | Mutable actions receive repository write capability | CWE-829 | .github/workflows/image_actions.yml:29 | Static lead | Both |
| #55 | Medium | Unversioned Playwright install can overwrite master | CWE-829 | .github/workflows/frontend-bundle-analysis.yml:39 | Static lead | Audn only |
| #56 | Medium | Unvalidated seed data can create administrators | CWE-20 | data/staticData.ts:55 | Static lead | Audn only |
| #57 | Medium | Application name injects executable HTML | CWE-79 | lib/startup/customizeApplication.ts:83 | Static lead | Audn only |
| #58 | Medium | Anonymous callers can forge product reviews | CWE-862 | routes/createProductReviews.ts:14 | Static lead | Audn only |
| #59 | Medium | Unverified JWT controls chatbot order identity | CWE-347 | routes/chat.ts:42 | Static lead | Both |
| #60 | Medium | Coupon policy enforced only by the LLM | CWE-862 | routes/chat.ts:176 | Static lead | Both |
| #61 | Medium | Default deployment exposes credentials over plain HTTP | CWE-319 | server.ts:130 | Static lead | Audn only |
| #62 | Medium | Bender account password exposed client-side | CWE-798 | frontend/src/hacking-instructor/challenges/loginBender.ts:75 | Static lead | Audn only |
| #63 | Medium | Jim account password exposed client-side | CWE-798 | frontend/src/hacking-instructor/challenges/loginJim.ts:64 | Static lead | Audn only |
| #64 | Medium | CAPTCHA response discloses its answer | CWE-200 | routes/captcha.ts:22 | Static lead | Audn only |
| #65 | Medium | Solved CAPTCHAs remain valid for unlimited reuse | CWE-294 | routes/captcha.ts:35 | Static lead | Audn only |
| #66 | Medium | Failed requests satisfy global anti-cheat checks | CWE-345 | lib/antiCheat.ts:51 | Static lead | Audn only |
| #67 | Medium | Committed CTF key permits flag forgery | CWE-321 | ctf.key:1 | Static lead | Audn only |
| #68 | Medium | Product link uses cleartext HTTP | CWE-319 | config/addo.yml:57 | Static lead | Audn only |
| #69 | Medium | Client clock controls campaign coupon validity | CWE-602 | frontend/src/app/payment/payment.component.ts:152 | Static lead | Audn only |
| #70 | Medium | Feedback accepts ratings outside the valid range | CWE-20 | models/feedback.ts:57 | Static lead | Audn only |
| #71 | Medium | Basket IDOR exposes other users' carts | CWE-639 | routes/basket.ts:18 | Static lead | Audn only |
| #72 | Medium | Duplicate BasketId bypasses basket ownership check | CWE-639 | routes/basketItems.ts:21 | Static lead | Audn only |
| #73 | Medium | Coupon update lacks basket ownership check | CWE-639 | routes/coupon.ts:11 | Static lead | Audn only |
| #74 | Medium | User-controlled layout enables local file disclosure | CWE-22 | routes/dataErasure.ts:103 | Static lead | Audn only |
| #75 | Medium | CAPTCHA answer disclosed in API response | CWE-200 | routes/imageCaptcha.ts:24 | Static lead | Audn only |
| #76 | Medium | Missing CAPTCHA record bypasses verification | CWE-693 | routes/imageCaptcha.ts:42 | Static lead | Audn only |
| #77 | Medium | Wallet debit permits concurrent overspending | CWE-362 | routes/order.ts:148 | Static lead | Audn only |
| #78 | Medium | Checkout lacks basket ownership validation | CWE-639 | routes/order.ts:34 | Static lead | Audn only |
| #79 | Medium | Array ID exposes multiple recycle records | CWE-639 | routes/recycles.ts:11 | Static lead | Audn only |
| #80 | Medium | Premium content served without authorization | CWE-862 | routes/premiumReward.ts:12 | Static lead | Audn only |
| #81 | Medium | Response discrepancy enables account enumeration | CWE-204 | routes/securityQuestion.ts:12 | Static lead | Audn only |
| #82 | Medium | Arbitrary wallet balance top-ups | CWE-20 | routes/wallet.ts:23 | Static lead | Audn only |
| #83 | Medium | Client header spoofs stored login IP | CWE-345 | routes/saveLoginIp.ts:18 | Static lead | Audn only |
| #84 | Medium | Masked email collisions expose other users' orders | CWE-639 | routes/orderHistory.ts:13 | Static lead | Audn only |
| #85 | Medium | Authentication token contains the TOTP seed | CWE-200 | routes/2fa.ts:26 | Static lead | Audn only |
| #86 | Medium | Unverified issue references defeat spam enforcement | CWE-840 | .github/workflows/pr-compliance.yml:275 | Static lead | Audn only |
| #87 | Medium | Any commenter can rebase pull requests | CWE-862 | .github/workflows/rebase.yml:3 | Static lead | Audn only |
| #88 | Medium | Lossy email masking breaks order ownership | CWE-187 | routes/chat.ts:158 | Static lead | Both |
| #89 | Medium | New commits bypass completed compliance decisions | CWE-367 | .github/workflows/pr-compliance.yml:3 | Static lead | Audn only |
| #90 | Medium | JWT algorithm confusion accepts forged tokens | CWE-347 | routes/verify.ts:111 | Static lead | Both |
| #91 | Medium | Anonymous users can access arbitrary orders | CWE-639 | routes/trackOrder.ts:12 | Static lead | Audn only |
| #92 | Medium | OAuth flow omits state validation | CWE-352 | frontend/src/app/login/login.component.ts:147 | Static lead | Audn only |
| #93 | Medium | Unanchored coupon validation accepts unbounded discounts | CWE-20 | lib/insecurity.ts:102 | Static lead | Audn only |
| #94 | Medium | Generated users share a hard-coded password | CWE-798 | data/datacreator.ts:310 | Static lead | Audn only |
| #95 | Low | Concurrent requests inflate review likes | CWE-362 | routes/likeProductReviews.ts:25 | Static lead | Audn only |
| #96 | Low | Public wallet address accepted as ownership proof | CWE-345 | routes/nftMint.ts:41 | Static lead | Both |
| #97 | Low | Profile update lacks CSRF enforcement | CWE-352 | routes/updateUserProfile.ts:16 | Static lead | Audn only |
| #98 | Low | Wallet ownership is never verified | CWE-862 | routes/web3Wallet.ts:14 | Static lead | Both |
| #99 | Low | TOTP secrets stored unencrypted | CWE-312 | routes/2fa.ts:105 | Static lead | Audn only |
| #100 | Info | Active user credentials embedded in client code | CWE-798 | frontend/src/hacking-instructor/challenges/exposedCredentials.ts:51 | Likely FP | Audn only |
| #101 | Info | Feedback XSS compromises administrator sessions | CWE-79 | frontend/src/app/administration/administration.component.ts:86 | Likely FP | Audn only |
| #102 | Info | Backslashes bypass log path validation | CWE-22 | routes/logfileServer.ts:9 | Likely FP | Audn only |
| #103 | Info | Backslashes bypass key-file path restriction | CWE-22 | routes/keyServer.ts:10 | Likely FP | Audn only |
| # | Sev | Finding | Key files | Overlap |
|---|---|---|---|---|
| #1 | High | Unpinned CI image actions receive repository token | .github/workflows/image_actions.yml, github/workflows/image_actions.yml | Both |
| #2 | High | Unpinned image workflow actions expose CI token | .github/workflows/image_actions.yml, github/workflows/image_actions.yml | Both |
| #3 | High | 2FA temporary JWTs accepted as bearer auth | server.ts, lib/insecurity.ts | Both |
| #4 | High | Global forged-JWT registration enables account takeover | lib/insecurity.ts, server.ts | Both |
| #5 | High | Release tag command injection in legacy website workflow | .github/workflows/update-news-www-legacy.yml, tab_news.md | Both |
| #6 | High | Unpinned npm installs in release and Docker builds | package-lock.js, bin/semver.js | Both |
| #7 | High | Chat order tool trusts unverified JWT identity | routes/chat.ts, server.ts | Both |
| #8 | High | Chat order tool trusts unsigned JWT identity | routes/chat.ts, lib/insecurity.ts | Both |
| #9 | Medium | Unbounded complaint similarity scan enables DoS | server.ts, routes/verify.ts | Codex only |
| #10 | Medium | Lazy Web3 imports race creates duplicate listeners | server.ts, routes/nftMint.ts | Both |
| #11 | Medium | Lazy ethers import races Web3 listener creation | routes/nftMint.ts, routes/web3Wallet.ts | Both |
| #12 | Medium | CI smoke test re-enables npm lifecycle scripts | .github/workflows/ci.yml, package.js | Both |
| #13 | Medium | Junie skill curls untrusted reference URLs | .junie/skills/add-reference/SKILL.md, REFERENCES.md | Codex only |
| #14 | Medium | Unsafe Junie curl crawling can expose local/internal resources | .junie/skills/add-reference/SKILL.md, junie/skills/add-reference/SKILL.md | Codex only |
| #15 | Medium | External Google Font leaks visitor metadata | config/ctf.yml, frontend/angular.js | Codex only |
| #16 | Low | Unconditional Google Fonts load leaks CTF visitor metadata | server.ts, frontend/angular.js | Codex only |
| #17 | Low | Windows i18n restore uses Unix-only basename parsing | en.js, lib/startup/restoreOverwrittenFilesWithOriginals.ts | Codex only |
| #18 | Info | Challenge name mismatch hides Hacking Instructor | data/static/challenges.yml, frontend/src/hacking-instructor/challenges/exposedCredentials.ts | Codex only |
| #19 | Info | Complaint length test no longer checks max boundary | frontend/src/app/complaint/complaint.component.spec.ts, frontend/src/app/complaint/complaint.component.ts | Codex only |
| #20 | Info | Missing snippet metadata now causes 500 errors | .info.yml, server.ts | Codex only |