Back to skill

Security audit

Secure Auth Patterns

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent authentication guide, but it includes unsafe auth code examples that could leak bearer tokens if copied into an application.

Install only if you treat it as reference material and manually correct the insecure examples. Do not copy the OAuth redirect pattern that puts access tokens in URLs; use secure HttpOnly cookies or a short-lived one-time code exchange instead, and regenerate session identifiers after login or privilege changes.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:195
Finding

OAuth Access Token Exposed in Redirect Query String

Content
View full analysis
{ const tokens = generateTokens(req.user); res.redirect(`${FRONTEND_URL}/auth/callback?token=${tokens.accessToken}`); }); ``` `resources/implementation-playbook.md:321-330`: ```typescript app.get( '/api/auth/google/callback', passport.authenticate('google', { session: false }), (req, res) => { // Generate JWT const tokens = generateTokens(req.user.id, req.user.email, req.user.role); // Redirect to frontend with token res.redirect(`${process.env.FRONTEND_URL}/auth/callback?token=${tokens.accessToken}`); } ); ``` ### Technical Analysis Both OAuth callback examples place a JWT access token directly in a redirect URL's query string. An access token is a bearer credential: possession is sufficient to authenticate as the represented user. URLs are routinely retained or transmitted through browser history, reverse-proxy and web-server access logs, monitoring systems, analytics platforms, screenshots, support diagnostics, and potentially referrer headers. Consequently, systems or personnel that do not require authentication credentials may receive the token. Although the examples issue short-lived access tokens, the exposure remains exploitable until the token expires. The examples also do not demonstrate single-use semantics or immediate revocation after disclosure. ### Attack Path 1. A victim completes authentication through the Google OAuth flow. 2. The callback generates an access token for the victim. 3. The server redirects the browser to `/auth/callback?token=`. 4. The URL or query string is captured in bro ...[truncated 918 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:143
Finding

Authenticated Session Established Without Session Identifier Regeneration

Content
View full analysis
{ const { email, password } = req.body; const user = await db.users.findOne({ email }); if (!user || !(await verifyPassword(password, user.passwordHash))) { return res.status(401).json({ error: 'Invalid credentials' }); } req.session.userId = user.id; req.session.role = user.role; res.json({ user: { id: user.id, email: user.email } }); }); ``` `resources/implementation-playbook.md:234-247`: ```typescript app.post('/api/auth/login', async (req, res) => { const { email, password } = req.body; const user = await db.users.findOne({ email }); if (!user || !(await verifyPassword(password, user.passwordHash))) { return res.status(401).json({ error: 'Invalid credentials' }); } // Store user in session req.session.userId = user.id; req.session.role = user.role; res.json({ user: { id: user.id, email: user.email, role: user.role } }); }); ``` ### Technical Analysis The login examples add authenticated user information to the existing session without regenerating its identifier after successful credential verification. Authentication is a privilege transition, and the session identifier should be replaced at that boundary. If an attacker can cause a victim to use a session identifier known to the attacker, or can otherwise obtain the identifier before authentication, retaining the same identifier after login allows the attacker to reuse it as an authenticated session. Secure cookie flags reduce several theft vectors but do not replace server-side session regeneration. ### Attack Path 1. An attacker obtains or fixes a session identifier associated with an unauthenticated session. Feasibility depends on the surround ...[truncated 1031 chars]
Remediation
View remediation
{ const { email, password } = req.body; const user = await db.users.findOne({ email }); if (!user || !(await verifyPassword(password, user.passwordHash))) { return res.status(401).json({ error: 'Invalid credentials' }); } req.session.regenerate((err) => { if (err) return next(err); req.session.userId = user.id; req.session.role = user.role; req.session.save((saveError) => { if (saveError) return next(saveError); res.json({ user: { id: user.id, email: user.email } }); }); }); }); ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 107)May include surrounding context.

md
return res.status(403).json({ error: 'Token revoked' });
    }
    
    // Generate new access token
    const user = await db.users.findById(payload.userId);
    const accessToken = jwt.sign(
      { userId: user.id, email: user.email, role: user.role },

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · resources/implementation-playbook.md (reported line 130)May include surrounding context.

md
return res.status(403).json({ error: 'Token revoked' });
    }
    
    // Generate new access token
    const user = await db.users.findById(payload.userId);
    const accessToken = jwt.sign(
      { userId: user.id, email: user.email, role: user.role },

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · resources/implementation-playbook.md (reported line 162)May include surrounding context.

md
return res.status(403).json({ error: 'Token revoked' });
    }
    
    // Generate new access token
    const user = await db.users.findById(payload.userId);
    const accessToken = jwt.sign(
      { userId: user.id, email: user.email, role: user.role },

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 341)May include surrounding context.

md
- Use HTTPS everywhere
- Hash passwords with bcrypt (12+ rounds)
- Use short-lived access tokens (15-30 min)
- Store refresh tokens in database (revocable)
- Validate all input
- Rate limit auth endpoints

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · resources/implementation-playbook.md (reported line 592)May include surrounding context.

md
1. **Never Store Plain Passwords**: Always hash with bcrypt/argon2
2. **Use HTTPS**: Encrypt data in transit
3. **Short-Lived Access Tokens**: 15-30 minutes max
4. **Secure Cookies**: httpOnly, secure, sameSite flags
5. **Validate All Input**: Email format, password strength
6. **Rate Limit Auth Endpoints**: Prevent brute force attacks

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The OAuth callback sample redirects the user with an access token embedded in the URL, and the documentation provides no warning that this is unsafe. This normalizes an insecure implementation pattern that can leak bearer tokens through logs, referers, browser history, and third-party monitoring systems.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The playbook explicitly warns against insecure token storage, yet the OAuth callback example transmits the access token in a URL query string. Tokens in URLs can be exposed through browser history, referrer headers, proxy logs, analytics tooling, and screenshots, which can lead to token theft and account compromise.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.