---
name: security-hardening-and-token-strategy
description: Apply current tibi-server security practices to website projects. Covers token strategy, secret handling, rate limiting, bulk-permission safety, cookie settings, risky hook capabilities, and secure operator decisions for this stack.
---

# security-hardening-and-token-strategy

## When to use this skill

Use this skill when:

- setting up or reviewing authentication and token usage on this stack
- deciding how admin tokens, JWT auth, and token permissions should be used
- hardening hooks, actions, and project config against current upstream security risks
- reviewing bulk permissions, rate limiting, cookies, secrets, or risky server-side capabilities

## Goal

Keep projects on this starter aligned with the current tibi-server security model and with the security-sensitive operator decisions the stack exposes.

This is not a generic web-security primer. It is the practical security workflow for this repo family.

## Source of truth

Use these sources when implementing or reviewing security decisions:

- `tibi-server/docs/05-authentication.md`
- `tibi-server/docs/14-security.md`
- `tibi-server/docs/17-field-level-permissions.md`
- `tibi-server/docs/02-configuration.md`
- project config and collection/action permission YAML files

## Security review order

When asked to harden a project, inspect in this order:

1. secret sourcing in config/env
2. token type and scope
3. collection/action permissions
4. bulk permission exposure
5. field-level restrictions
6. rate limiting and cookie settings
7. risky hook capabilities such as outbound fetch or exec

This prevents “secure enough” changes that leave the real attack surface untouched.

## Authentication surfaces

This stack exposes multiple auth mechanisms. Do not mix them casually.

- JWT user auth
- refresh-token cookie flow
- admin tokens
- token-based permission sets for narrower machine access

Recommended default:

- use JWT user auth for real users and editor/admin sessions
- use refresh cookies for session continuation where appropriate
- use admin tokens only for system/admin/ops flows that truly need them
- use token permissions for narrow machine integrations

## Token header distinction

Use the right header for the right surface:

- system-level API such as project CRUD, admin reload, shutdown: `X-Admin-Token`
- collection-level CRUD via static project token: `Token`
- JWT-authenticated user flow: `X-Auth-Token`

Do not assume a working `Token` header implies system-level admin rights.

## Secret handling

Do not keep production secrets as committed literals if the deployment can source them from env or operator-managed secrets.

Review at minimum:

- JWT secrets
- SMTP credentials
- admin tokens
- external API keys
- LLM/embedding provider keys

If secrets are hardcoded in committed config, treat that as a structural problem, not as cleanup trivia.

## Bulk permission safety

Bulk operations are more dangerous than single-document mutations.

Important rule:

- boolean `post: true` / `put: true` / `delete: true` does not imply bulk access
- bulk requires object-form permissions with `bulk: true`

Example:

```yaml
permissions:
    user:
        methods:
            post:
                allow: true
                bulk: true
```

Do not enable bulk access casually in website projects. Most editorial workflows do not need it.

## Field-level security

Security on this stack is not only collection-method based.

Review all of these layers together:

- collection methods
- `readonlyFields`
- `hiddenFields`
- field-level `readonly` / `hidden`
- eval-based field rules
- collection visibility in the admin UI

If a field should not be editable or visible, enforce that on the server. Do not rely on frontend omission.

## Rate limiting and login hardening

Current upstream tibi-server supports login rate limiting with exponential backoff.

Review these config points:

- `ratelimit.enabled`
- `ratelimit.loginInitialDelay`
- `ratelimit.loginMaxDelay`
- `ratelimit.loginResetAfter`

Security implication:

- a project may look fine in normal use while still being too soft against brute-force attempts if rate limiting is not configured as expected

For serious deployments, do not leave this unreviewed just because login works.

## Cookie and session hardening

Refresh-token flows should respect the target environment.

Review:

- `api.secureCookies`
- HTTPS vs local HTTP expectations
- whether debugging shortcuts are accidentally bleeding into production config

Do not weaken secure-cookie behavior globally just to make a dev shortcut work.

## Query-parameter token risk

Token-based permissions can be passed via query parameters in some cases, but this is a documented risk surface.

If query tokens are unavoidable:

- scope them narrowly
- avoid logging full URLs with sensitive query strings
- understand proxy, history, and referrer exposure

Prefer header-based transport whenever possible.

## Risky hook capabilities

Current tibi-server exposes powerful capabilities in hooks. Treat them as explicit design decisions, not utilities.

Particularly important:

- `context.http.fetch()` / `context.http.fetchStream()` can create SSRF risk
- `context.exec.command()` can create command-execution risk
- broad filesystem/network access in hooks should not be treated as harmless

If a feature can be implemented without shell execution or arbitrary internal fetches, prefer the safer path.

When such capabilities are used, document:

- why they are necessary
- what the allowed target surface is
- what the safer rejected alternatives were

## CORS configuration

CORS follows a hierarchy. Configure it deliberately instead of widening it reactively.

Levels:

- server-level `config.yml`
- project-level `api/config.yml`
- collection/action-level YAML overrides

For typical website projects on this starter, the default proxy setup often means no aggressive cross-origin opening is required. Add explicit CORS only when the real deployment needs external origins.

## Recommended implementation patterns

### Public form workflow

Recommended shape:

- public action with narrow methods
- server-side validation
- no admin token in the browser
- separate internal persistence only when truly required

### Integration token

Recommended shape:

- dedicated narrow token permission set
- minimal collection/action scope
- header-based transport preferred

### Sensitive internal fields

Recommended shape:

- use hidden/readonly restrictions explicitly
- keep admin UI aligned with those restrictions
- do not let previews depend on hidden-only data

### Hook that calls external systems

Recommended shape:

- fixed or validated targets
- no user-controlled arbitrary internal fetches
- no shell execution unless unavoidable

## Anti-patterns

- hardcoded production secrets in committed config
- broad admin tokens used for normal frontend or integration traffic
- bulk permissions enabled without a concrete operator need
- risky hook capabilities treated as harmless helpers
- collection security solved in the UI instead of the server
- production cookie or rate-limit settings weakened for convenience

## Verification checklist

After security-relevant changes, verify all of these:

1. secrets are sourced appropriately
2. token type matches the intended actor and scope
3. bulk permissions are not broader than necessary
4. readonly/hidden behavior is correct on the API
5. rate limiting and cookie settings match the environment
6. risky hook capabilities are constrained by design
7. `yarn validate` stays clean

## What an LLM should inspect first

When asked to harden or design secure access on this starter, inspect in this order:

1. `tibi-server/docs/05-authentication.md`
2. `tibi-server/docs/14-security.md`
3. `tibi-server/docs/17-field-level-permissions.md`
4. the relevant collection/action permission sets
5. secret sourcing in config/env
6. whether hooks use risky capabilities like outbound fetch or exec

This prevents working implementations that quietly widen the attack surface.
