Back to skill

Security audit

hono

Security checks for vulnerabilities and agentic risk

Overview

This is a documentation-only Hono framework skill with some insecure or incomplete example patterns that users should not copy into production unchanged.

Install is acceptable if you treat this as a quick Hono reference, not production-ready security guidance. Replace all sample secrets, use secure cookie attributes, sanitize error responses, restrict CORS, and review proxy destinations before deploying code generated from these examples.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:126
Finding

Internal Exception Messages Exposed in HTTP Responses

Content
View full analysis
{ return c.json({ error: err.message }, 500) }) ``` A similar pattern appears in `references/routing.md`: ```ts app.onError((err, c) => { console.error(err) return c.json({ error: err.message }, 500) }) ``` The RPC documentation also exposes global exception messages: ```ts const app = new Hono() .get('/users', (c) => c.json({ users: [] })) .onError((err, c) => c.json({ error: err.message }, 500)) type AppWithErrors = ApplyGlobalResponse ``` ### Technical Analysis The examples serialize the unfiltered `Error.message` value into remotely accessible HTTP responses. Exception messages from databases, storage adapters, parsers, authentication components, and third-party services may include implementation details such as: - Database schema, query, or constraint information - Local filesystem paths - Dependency and runtime details - Internal service names and endpoints - Authentication or authorization state - Portions of malformed or sensitive input Because this Skill is documentation intended to guide generated application code, users or agents may copy this pattern into production services. The issue does not directly compromise the machine running the Skill, but it can create an information-disclosure vulnerability in applications built from the guidance. ### Attack Path 1. An attacker submits malformed input or invokes a route that triggers an unhandled exception. 2. Hono passes the exception to the global `onError` handler. 3. The handler serializes `err.message` into a JSON response. 4. The attacker collects internal implementation details from repeated error responses. 5. The disclosed details ...[truncated 549 chars]
Remediation
View remediation
{ console.error('Unhandled request error', { requestId: c.get('requestId'), error: err, }) return c.json( { error: 'Internal Server Error', requestId: c.get('requestId'), }, 500 ) }) ``` Additional hardening should include: 1. Generate and return a non-sensitive request or incident identifier for support correlation. 2. Prevent secrets, authorization headers, cookies, and request bodies from being written to ordinary logs. 3. Map expected validation and application errors to explicit sanitized responses. 4. Restrict detailed stack traces and debugging responses to local development. 5. Add tests confirming that stack traces, paths, database messages, and secrets never appear in production responses. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/middleware.md:66
Finding

Hardcoded Authentication Secrets and Predictable Credentials in Examples

Content
View full analysis
{ const token = sign({ sub: 'user123', name: 'Alice' }, secret) return c.json({ token }) }) ``` The session examples use a predictable identifier: ```ts app.post('/login', (c) => { c.cookie('session', 'abc123', { httpOnly: true }) return c.json({ ok: true }) }) ``` ### Technical Analysis The values are illustrative placeholders rather than evidence of exposed production credentials. Nevertheless, the documentation presents fixed secrets directly in deployable authentication examples without consistently warning that they must be replaced. If copied into an application, these values make bearer authentication, Basic Authentication, JWT signing, or session management predictable. A hardcoded JWT secret permits attackers who know the example to sign arbitrary tokens. A fixed bearer token or password can be replayed directly. A fixed session identifier allows straightforward session impersonation. Hardcoded secrets are also difficult to rotate, commonly enter source-control history, and may be propagated into build artifacts, logs, or publicly distributed repositories. ### Attack Path 1. A developer or code-generation agent copies the authenticatio ...[truncated 1063 chars]
Remediation
View remediation
() app.use('/api/*', async (c, next) => { const secret = c.env.API_BEARER_TOKEN if (!secret) { throw new Error('Authentication secret is not configured') } return bearerAuth({ token: secret })(c, next) }) ``` For sessions, generate cryptographically secure, unique identifiers and store only a verifier or hash server-side: ```ts const sessionId = crypto.randomUUID() ``` The documentation should also: 1. Explicitly state that sample values must never be used in production. 2. Prefer environment variables or managed runtime secret stores. 3. Fail closed when a secret is missing rather than using a default. 4. Require high-entropy JWT keys appropriate for the selected algorithm. 5. Document key rotation, token expiration, audience, issuer, and algorithm validation. 6. Add secret-scanning checks to CI and prevent credentials from entering source control. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/rpc.md:143
Finding

Session Cookie Examples Omit Required Transport and Cross-Site Protections

Content
View full analysis
{ c.cookie('session', 'abc123', { httpOnly: true }) return c.json({ ok: true }) }) ``` The Context API also demonstrates an unprotected default cookie before presenting a stronger separate example: ```ts c.cookie('session', 'abc123') c.cookie('theme', 'dark', { path: '/', httpOnly: true, secure: true, sameSite: 'Strict', maxAge: 60 * 60 * 24, }) ``` ### Technical Analysis The session-cookie example sets `httpOnly` but omits `secure` and `sameSite`. It also uses a predictable session value and does not define an explicit lifetime or path. `httpOnly` helps prevent direct JavaScript access but does not ensure transport confidentiality and does not independently mitigate cross-site request forgery. Without `secure`, a cookie may be sent over an unencrypted HTTP connection under some deployment configurations. Without an appropriate `sameSite` policy or an independent anti-CSRF mechanism, browsers may attach the session cookie to attacker-initiated cross-site requests. The actual behavior depends on browser defaults and deployment infrastructure, so exploitation is conditional. However, security-sensitive documentation should provide a secure default rather than rely on implicit browser behavior. ### Attack Path A CSRF-oriented exploitation path is: 1. A victim authenticates to an application built from the example. 2. The server creates a session cookie without an explicit restrictive `sameSite` policy. 3. The victim visits an attacker-controlled page. 4. The page causes the browser to submit a request to a state-changing application endpoint. 5. If the browser and application configuration permit the cookie on that request and the server has no i ...[truncated 834 chars]
Remediation
View remediation
{ const sessionId = crypto.randomUUID() // Store a secure verifier for sessionId in server-side session storage. c.cookie('session', sessionId, { path: '/', httpOnly: true, secure: true, sameSite: 'Strict', maxAge: 60 * 60, }) return c.json({ ok: true }) }) ``` Additional controls should include: 1. Generate high-entropy, unique session identifiers using a cryptographically secure generator. 2. Regenerate the session identifier after authentication and privilege changes. 3. Prefer `SameSite=Strict`; use `Lax` only where application workflows require it. 4. If cross-site cookies require `SameSite=None`, require `Secure` and implement robust anti-CSRF tokens plus `Origin` or `Referer` validation. 5. Enforce HTTPS and HSTS at the deployment boundary. 6. Scope cookies to the narrowest viable domain and path. 7. Define absolute and idle expiration, server-side revocation, and logout invalidation. 8. Avoid showing insecure shorthand forms such as `c.cookie('session', value)` for authentication cookies. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/helpers.md (reported line 234)May include surrounding context.

md
app.get('/proxy', proxy('https://api.example.com'))

// With transform
app.get('/api', proxy('https://api.example.com/v1', {
  rewriteRequest: (url) => {
    url.pathname = '/api' + url.pathname
  },

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
88% confidence
Finding

The example shows app.use('*', cors()) with a comment indicating 'Allow all origins (dev)'. Even though labeled for development, documentation examples are often copied into production, and permissive CORS can expose authenticated API responses or enable unintended cross-origin interaction when combined with credentials, weak auth, or browser-trusted flows.

Content

Scanner excerpt · references/middleware.md (reported line 37)May include surrounding context.

ts
import { cors } from 'hono/middleware'

// Allow all origins (dev)
app.use('*', cors())

// Production config

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation states that app.use('/api/*', authenticate()) is applied while also claiming /api/public skips auth, but that route still matches /api/* and would be protected unless additional exclusion logic is present. Developers following this example may wrongly expose or misconfigure public and protected endpoints, causing broken access control or deployment-time security assumptions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The example labels the third argument as metadata or a pre-handler construct, but the code behaves like an executable handler that can return a 401 response. This can mislead developers into placing authorization or side-effecting logic where they believe they are only attaching metadata, resulting in unexpected control flow and potentially bypassed or inconsistent security checks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file documents a proxy helper that forwards requests to an external API, which can transmit user or system data off-box. The section shows how to enable proxying but does not include any warning about privacy, data disclosure, or external request behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The natural-language description states that the middleware sets c.var.language based on the Accept-Language header. This reflects automatic locale selection rather than an explicit user choice, which can conflict with language/locale policy when no opt-in or override is documented.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.