Security Considerations for k-skill: A Defense-in-Depth Analysis
The k-skill project adopts a defense-in-depth security model that protects API secrets through environment-variable isolation, runtime sandboxing, and strict CI controls.
This open-source skill ecosystem (NomaDamas/k-skill) connects independent "skills" to public and free APIs. Because many integrations require authentication tokens, the codebase implements layered protections to prevent credential exposure while maintaining developer flexibility. This guide examines the specific security mechanisms built into the proxy server, browser runtime, and continuous integration pipeline.
Secret Handling Through Environment Variables
Hard-coded credentials are strictly prohibited throughout k-skill. All sensitive values flow through process.env, falling back to safe defaults when absent.
In packages/k-skill-proxy/src/server.js, the proxy base URL resolves through a priority chain that never exposes secrets in source files:
function getProxyBaseUrl(options = {}) {
// Uses explicit option, then env var, then defaults
return (
options.proxyBaseUrl ||
process.env.KSKILL_PROXY_BASE_URL ||
"https://k-skill-proxy.nomadamas.org"
);
}
Similarly, Data.go.kr API keys and other provider credentials follow identical patterns. If an environment variable is missing, the code defaults to an empty string or safe placeholder rather than failing open.
Free-API Proxy Policy and Attack Surface Reduction
The k-skill-proxy package enforces a strict routing policy documented in docs/deploy-k-skill-proxy.md. Public endpoints without authentication requirements are called directly from the user's machine, bypassing the proxy entirely.
This design limits proxy traffic to only those free APIs that mandate key-based authentication—such as Data.go.kr—preventing unnecessary request centralization and reducing DDoS exposure. The proxy layer also implements:
- Configurable rate limiting via environment variables
- Optional caching layers to prevent API abuse
- No credential storage in logs or response bodies
Runtime Isolation with k-skill-browser-runtime
Skills requiring browser automation depend on packages/k-skill-browser-runtime/src/provider.js. This abstraction prevents direct Chrome DevTools Protocol (CDP) manipulation and isolates each skill's session context.
The provider selection logic reads from KSKILL_BROWSER_PROVIDER without exposing the resolved value:
function resolveProvider(env = process.env) {
const provider = env.KSKILL_BROWSER_PROVIDER || "auto";
return String(provider).trim();
}
This isolation prevents:
- Cross-skill cookie leakage
- Authentication token persistence between sessions
- Accidental credential spills through shared browser state
CI Security Controls and Secret Scrubbing
The GitHub Actions workflow in .github/workflows/ci.yml executes npm run ci in a clean environment. Tests that require temporary credentials follow a strict injection-and-cleanup pattern demonstrated in packages/public-restroom-nearby/test/index.test.js:
test("public restroom search uses API key", async () => {
const original = process.env.KAKAO_REST_API_KEY;
process.env.KAKAO_REST_API_KEY = "dummy-key";
await runSearch(); // skill code reads the env var
process.env.KAKAO_REST_API_KEY = original; // restore immediately
});
Critical CI security practices include:
- No persistent secrets in the test environment
- Immediate environment variable restoration post-test
- No credential retention in CI logs
Dependency Safety and Auditability
The repository leverages npm workspaces and Changesets for version management, eliminating manual version pinning that could introduce vulnerable dependencies. Each skill publishes a skill.json manifest declaring required permissions—such as login requirements—enabling downstream consumers to audit data access risks before installation.
Summary
- Environment-only secrets: All credentials resolve through
process.envwith safe defaults inserver.jsand provider configurations. - Selective proxy routing: Free APIs without keys bypass the proxy; authenticated traffic routes through rate-limited, non-logging infrastructure.
- Browser sandboxing:
k-skill-browser-runtimeabstracts CDP connections and isolates per-skill sessions viaprovider.js. - Ephemeral CI credentials: Tests inject and immediately clear API keys, preventing secret persistence in logs or long-running processes.
- Manifest-based permissions:
skill.jsonfiles document required access levels for ecosystem auditability.
Frequently Asked Questions
How does k-skill prevent API key leaks in source code?
The codebase enforces a strict policy: no hard-coded credentials. Every sensitive value reads from environment variables like process.env.DATA_GO_KR_API_KEY or process.env.KSKILL_PROXY_BASE_URL, defaulting to empty strings or safe fallbacks when unset. This pattern appears consistently in server.js and throughout the monorepo.
Is the k-skill-proxy safe to expose publicly?
The proxy intentionally restricts traffic to free APIs requiring authentication keys. Public endpoints are excluded from proxy routing, reducing the attack surface. Additionally, the server implements rate limiting, optional caching, and never logs or returns credentials in HTTP responses.
What prevents browser-based skills from leaking session data?
The k-skill-browser-runtime package in provider.js abstracts all CDP connections. Each skill receives an isolated browser context—cookies and tokens do not persist across invocations, and the KSKILL_BROWSER_PROVIDER environment variable controls provider selection without exposing sensitive configuration values.
How are secrets handled during continuous integration?
CI pipelines in .github/workflows/ci.yml run without persistent secrets. When tests require credentials, they temporarily inject values into process.env, execute the test, and immediately restore the original value—preventing secret retention in logs or environment dumps.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →