Skip to content

feat: add client-secret-exposure-audit skill - #1422

Open
siddanta-ar1 wants to merge 1 commit into
sickn33:mainfrom
siddanta-ar1:feat/client-secret-exposure-audit
Open

feat: add client-secret-exposure-audit skill#1422
siddanta-ar1 wants to merge 1 commit into
sickn33:mainfrom
siddanta-ar1:feat/client-secret-exposure-audit

Conversation

@siddanta-ar1

Copy link
Copy Markdown

What

Adds a new client-secret-exposure-audit skill under
skills/client-secret-exposure-audit/ — a defensive, read-only workflow for
finding secrets and sensitive files that a deployed web app exposes to the
browser.

Why

The catalog has web-security-testing for the broad OWASP Top 10, but nothing
focused on the very common, high-impact case of credentials leaking into the
client surface
: hardcoded keys/tokens in JS, secrets in HTML
meta/data-*/comments, and server-side source/config/deploy files left
publicly reachable behind an SPA catch-all. This skill fills that gap.

Maps to OWASP A02:2021 (Cryptographic Failures / sensitive data exposure) and
A05:2021 (Security Misconfiguration); CWE-798, CWE-200, CWE-540, CWE-942,
CWE-338.

Contents

  • SKILL.md — 6-phase workflow (headers → HTML → JS bundles → source/config/deploy
    file probing with SPA-fallback size baselining → triage/severity → reporting),
    a secret-pattern grep set, a severity table, and generalized curl/grep
    commands driven by a single $BASE variable so it works on any authorized
    target.
  • example-report.md — a full worked report format, produced by running the skill
    against a public, intentionally-vulnerable teaching demo
    (demo-for-opensource.vercel.app, whose own source states its secrets are fake).

Safety

  • risk: safe — the workflow performs only unauthenticated GET requests for
    resources the server already serves publicly; no exploitation, brute force, or
    mutation.
  • Explicit authorized-targets-only guidance and secret-redaction/rotation advice
    in the Security & Safety Notes section.

Validation

  • python3 tools/scripts/validate_skills.py → all skills pass
  • python3 tools/scripts/validate_skills.py --strict → all skills pass
  • node tools/scripts/tests/docs_security_content.test.js → exit 0

Source-only PR: no generated registry artifacts (CATALOG.md, skills_index.json,
data/*.json) included.

🤖 Generated with Claude Code

https://claude.ai/code/session_015PmSa2TM63N7R5mGCzVriS

Defensive, read-only workflow to audit a deployed web app for secrets
and sensitive files exposed to the browser: hardcoded API keys/tokens in
JS, secrets in HTML meta/data-*/comments, publicly reachable
source/config/deploy files, and header/CORS misconfiguration. Maps to
OWASP A02/A05 and CWE-798/200/540. Includes a worked example-report.md.
Copilot AI lite review requested due to automatic review settings September 10, 2026 06:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical and moderate findings affect request scope, redaction, bundle coverage, file verification, and CORS guidance.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a defensive, read-only skill for auditing browser-exposed secrets and sensitive deployment files.

Changes:

  • Adds a six-phase GET-only audit workflow.
  • Documents secret patterns, severity, safety, and remediation guidance.
  • Adds a worked example report.
File summaries
File Description
skills/client-secret-exposure-audit/SKILL.md Defines the audit workflow, commands, and security guidance.
skills/client-secret-exposure-audit/example-report.md Demonstrates findings and remediation reporting.
Review details

Suppressed comments (5)

skills/client-secret-exposure-audit/SKILL.md:98

  • The workflow says to scan sourcemaps, but the preceding commands only discover and download .js URLs; they never inspect sourceMappingURL comments or fetch *.js.map files. An exposed map can therefore contain the very server-side source/secrets this audit is meant to find without being scanned.
Also scan any sourcemaps (`*.js.map`) — they can rebuild original source with
comments intact.

skills/client-secret-exposure-audit/SKILL.md:154

  • This copy-paste example sends a request to a real third-party host even though the skill requires explicit authorization for exact hostnames. A site being public or intentionally vulnerable does not establish permission; use a reserved placeholder/local target here and label the output as illustrative.
BASE="https://demo-for-opensource.vercel.app"; curl -s "$BASE/" -o body.html
grep -inE "recaptcha-secret|data-aws-secret|data-webhook-secret|mongodb\+srv" body.html
# -> meta recaptcha-secret=..., data-aws-access=AKIA…/data-aws-secret=…,
#    data-webhook-secret=whsec_…, and a hidden JSON blob with a mongodb+srv URI
#    (username:password@cluster). All reachable with a single unauthenticated GET.

skills/client-secret-exposure-audit/SKILL.md:94

  • This is the only JavaScript grep, but the severity table and worked report also claim findings for Math.random(), X-Rate-Limit-Bypass, and secret logging. Following the documented commands cannot discover those findings; add explicit patterns here or remove those out-of-scope findings from the workflow/report.
grep -rinE "secret|password|api[_-]?key|token|bearer|sk_(live|test)|pk_(live|test)|\
whsec_|akia|aiza|jwt|signing[_-]?key|admin[_-]?token|mongodb|redis://" js_* 2>/dev/null

skills/client-secret-exposure-audit/example-report.md:1

  • The repository's approval-safe path policy only recognizes skills/<id>/SKILL.md and support files under assets/, references/, or resources/ (tools/lib/workflow-contract.js:28-31). A sibling example-report.md is therefore classified as an unapproved path, so this source-only skill change cannot use the normal approval-safe flow; move the report under references/ (and update the links).
# Example Audit Report — Client-Side Secret & Sensitive-File Exposure

skills/client-secret-exposure-audit/example-report.md:69

  • This evidence does not confirm that the paths are real files: a custom error page can have a different size, and a real file can share the fallback size. Present size differences as candidates and verify the response before claiming the deployment exposes these files.
- **Evidence:** Each returns a distinct body size from the SPA catch-all page and
  contains real source/config (route definitions, internal service tokens such as
  • Files reviewed: 2/2 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +72 to +74
grep -inE "secret|passwd|password|api[_-]?key|apikey|token|bearer|authorization|\
akia|sk_live|sk_test|pk_live|whsec_|ghp_|aiza|private[_-]?key|mongodb(\+srv)?://|\
data-[a-z-]*(secret|token|key|access)" body.html
# extract script srcs, resolve relative paths against $BASE, fetch and scan
grep -ioE 'src="[^"]+\.js"' body.html | sed -E 's/^src="//; s/"$//' \
| while read -r p; do
u="$p"; case "$p" in http*) ;; /*) u="$BASE$p";; *) u="$BASE/$p";; esac
Comment on lines +87 to +88
grep -ioE 'src="[^"]+\.js"' body.html | sed -E 's/^src="//; s/"$//' \
| while read -r p; do
Comment on lines +113 to +115
read -r code size < <(curl -s -o /dev/null -w "%{http_code} %{size_download}" "$BASE$p")
[ "$code" = "200" ] && [ "$size" != "$FALLBACK" ] && echo "REAL FILE $code $size $p"
done
|---|---|
| **Critical** | Live provider secret keys (`sk_live_`, cloud `AKIA…`+secret, DB URI with password, private signing/JWT secret, admin bearer token) reachable anonymously |
| **High** | Server-side source/config/deploy files exposed; test-mode secret keys; internal service tokens; webhook signing secrets |
| **Medium** | CORS `*`, missing CSP/security headers, verbose banners, weak randomness for security values (`Math.random()` for tokens/refs) |
Comment on lines +102 to +103
- **Impact:** Any origin can read responses; dangerous if any endpoint returns
user/authenticated data.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e728c51e05

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

### Step 1: Fetch the page and inspect response headers

```bash
curl -s -D headers.txt -o body.html "$BASE/"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Follow redirects before scanning the target

When an authorized hostname redirects, such as an apex domain redirecting to www, Step 1 saves the redirect response rather than the application, and the later bundle and file probes continue using the original host. curl --help all documents -L, --location as “Follow redirects”; without it, the HTML scan can be empty and Step 4 discards redirect responses because they are not 200, yielding a false-clean audit. Follow redirects consistently and evaluate the final URL/status.

AGENTS.md reference: AGENTS.md:L54-L54

Useful? React with 👍 / 👎.


```bash
# extract script srcs, resolve relative paths against $BASE, fetch and scan
grep -ioE 'src="[^"]+\.js"' body.html | sed -E 's/^src="//; s/"$//' \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Traverse JavaScript beyond bare double-quoted URLs

On common builds where script URLs contain cache-busting queries such as app.js?v=1, use single-quoted attributes, or load route-split chunks through dynamic imports, this expression omits browser-loaded JavaScript because it only accepts src="...js" from the initial HTML. Secrets in those omitted bundles therefore produce a false-clean result despite the section claiming to pull every bundle; include query/quote variants and recursively discover preload, manifest, and imported chunks.

AGENTS.md reference: AGENTS.md:L54-L54

Useful? React with 👍 / 👎.

Comment on lines +113 to +114
read -r code size < <(curl -s -o /dev/null -w "%{http_code} %{size_download}" "$BASE$p")
[ "$code" = "200" ] && [ "$size" != "$FALLBACK" ] && echo "REAL FILE $code $size $p"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify fallback content before calling a path real

When a 200 catch-all embeds the requested path, a request ID, a nonce, or other dynamic content, its size differs between requests, so this condition labels every probed path as a real exposed file even though each is still the fallback; a real file with the same byte count is missed conversely. A length mismatch is not proof of file identity, so fetch candidates and validate their content/type or compare normalized bodies before reporting exposure.

AGENTS.md reference: AGENTS.md:L54-L54

Useful? React with 👍 / 👎.

Comment on lines +62 to +63
- `access-control-allow-origin: *` — permissive CORS (worse when paired with
credentials).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require exploitable context before flagging wildcard CORS

For the public page inspected in Step 1, Access-Control-Allow-Origin: * only permits cross-origin reading of data already anonymously available, while browsers reject wildcard origins for credentialed requests. Flagging the header by itself—and later rating it Medium—therefore creates a false vulnerability finding; require a sensitive response plus an exploitable origin policy, such as reflected or weakly matched origins with credentials, consistent with skills/cloudflare-security-audit/references/CLIENT-SIDE.md:36-37.

AGENTS.md reference: AGENTS.md:L54-L54

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants