✨ feat: enhance medialib image handling and add asset URL resolution
- Implemented `resolveApiAssetUrl` function to normalize asset URLs based on API base. - Updated `MedialibImage` component to utilize new asset URL resolution and added support for alt text and class properties. - Enhanced image loading behavior with improved width measurement and focal point handling. - Added placeholder image handling and improved accessibility with alt text. - Introduced new test script for auditing broken links in skill documentation. - Expanded seeded test content to include medialib entries and updated related tests for pagebuilder previews. - Improved global setup and teardown logging for clarity on seeded content management.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: security-hardening-and-token-strategy
|
||||
description: Apply current tibi-server security practices to website projects. Covers secret handling, token strategies, bulk-permission safety, cookie settings, SSRF/exec risks in hooks, and secure operator decisions for this stack.
|
||||
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
|
||||
@@ -9,150 +9,199 @@ description: Apply current tibi-server security practices to website projects. C
|
||||
|
||||
Use this skill when:
|
||||
|
||||
- Setting up or reviewing authentication and token use on this stack
|
||||
- Deciding how admin tokens, JWT auth, and token permissions should be used
|
||||
- Hardening hooks, actions, and project config against obvious security mistakes
|
||||
- Reviewing bulk permissions, secrets, cookie settings, or risky server-side capabilities
|
||||
- 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
|
||||
|
||||
The goal is to keep projects on this starter aligned with the current tibi-server security model and known risk areas.
|
||||
Keep projects on this starter aligned with the current tibi-server security model and with the security-sensitive operator decisions the stack exposes.
|
||||
|
||||
This skill is not a generic web security guide. It is about the concrete operator and implementation choices this 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-related decisions:
|
||||
Use these sources when implementing or reviewing security decisions:
|
||||
|
||||
- `tibi-server/docs/05-authentication.md`
|
||||
- `tibi-server/docs/14-security.md`
|
||||
- relevant collection/action permissions in `api/`
|
||||
- project environment/config files
|
||||
- `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:
|
||||
This stack exposes multiple auth mechanisms. Do not mix them casually.
|
||||
|
||||
- JWT user auth
|
||||
- refresh token cookie flow
|
||||
- refresh-token cookie flow
|
||||
- admin tokens
|
||||
- token-based permissions for API-style access
|
||||
- token-based permission sets for narrower machine access
|
||||
|
||||
Do not mix them casually. Each one has a different operational purpose.
|
||||
Recommended default:
|
||||
|
||||
## Recommended token strategy
|
||||
- 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
|
||||
|
||||
Use:
|
||||
## Token header distinction
|
||||
|
||||
- **JWT user auth** for real users in admin or authenticated workflows
|
||||
- **refresh cookies** for session continuation where appropriate
|
||||
- **admin tokens** only for server/admin/ops scenarios that truly need that level of access
|
||||
- **token permissions** for narrow integration access or machine clients
|
||||
Use the right header for the right surface:
|
||||
|
||||
Avoid using broad admin tokens where a narrow project or collection-level token permission is enough.
|
||||
- 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`
|
||||
|
||||
## Secrets handling
|
||||
Do not assume a working `Token` header implies system-level admin rights.
|
||||
|
||||
Do not keep production secrets as plain literals in committed config.
|
||||
## Secret handling
|
||||
|
||||
Prefer environment-variable substitution for:
|
||||
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
|
||||
- LLM API keys
|
||||
- external API tokens
|
||||
- admin token values
|
||||
- admin tokens
|
||||
- external API keys
|
||||
- LLM/embedding provider keys
|
||||
|
||||
If a project ships real secrets in config, treat that as a structural problem, not a cosmetic cleanup.
|
||||
If secrets are hardcoded in committed config, treat that as a structural problem, not as cleanup trivia.
|
||||
|
||||
## Bulk permission safety
|
||||
|
||||
Bulk mutations are explicitly more dangerous than single-document mutations.
|
||||
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`
|
||||
|
||||
Do not enable bulk operations casually in website projects. Most editor workflows do not need them.
|
||||
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
|
||||
|
||||
For refresh-token flows, ensure the deployment matches secure cookie expectations.
|
||||
Refresh-token flows should respect the target environment.
|
||||
|
||||
Important considerations:
|
||||
Review:
|
||||
|
||||
- secure cookies should stay enabled in HTTPS environments
|
||||
- local non-HTTPS development may need explicit relaxation
|
||||
- do not debug production cookie issues by weakening production defaults globally
|
||||
- `api.secureCookies`
|
||||
- HTTPS vs local HTTP expectations
|
||||
- whether debugging shortcuts are accidentally bleeding into production config
|
||||
|
||||
## Hook risk surfaces
|
||||
Do not weaken secure-cookie behavior globally just to make a dev shortcut work.
|
||||
|
||||
Current tibi-server exposes powerful server-side capabilities. Some of them require explicit restraint.
|
||||
## 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:
|
||||
|
||||
- `http.fetch` / `http.fetchStream` can create SSRF risk
|
||||
- `exec.command` can create command-execution risk
|
||||
- `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.
|
||||
|
||||
## Query-parameter token risk
|
||||
When such capabilities are used, document:
|
||||
|
||||
Token permissions may be passed through query parameters for specific cases, but this is a documented risk surface.
|
||||
|
||||
Prefer header-based token transport when possible.
|
||||
|
||||
If query tokens are unavoidable:
|
||||
|
||||
- avoid logging full URLs with sensitive query strings
|
||||
- understand proxy/referrer/history exposure
|
||||
- scope the token as narrowly as possible
|
||||
|
||||
## Permission boundaries
|
||||
|
||||
Security on this stack is layered.
|
||||
|
||||
Think in terms of:
|
||||
|
||||
- project visibility
|
||||
- collection method permissions
|
||||
- field-level restrictions
|
||||
- token scope
|
||||
- public vs authenticated action access
|
||||
|
||||
Do not rely on frontend hiding or convention where server-side permissions should be explicit.
|
||||
- why they are necessary
|
||||
- what the allowed target surface is
|
||||
- what the safer rejected alternatives were
|
||||
|
||||
## CORS configuration
|
||||
|
||||
CORS follows a 3-level hierarchy. Configure it in `api/config.yml` under `cors:` for project-wide settings, or in individual collection/action YAML for per-endpoint overrides:
|
||||
CORS follows a hierarchy. Configure it deliberately instead of widening it reactively.
|
||||
|
||||
| Level | Configuration location | Scope |
|
||||
|-------|----------------------|-------|
|
||||
| Server | tibi-server `config.yml` | Global default |
|
||||
| Project | `api/config.yml` → `cors:` | Per project |
|
||||
| Collection/Action | Collection or action YAML → `cors:` | Per endpoint |
|
||||
Levels:
|
||||
|
||||
Each level can `merge: true` (append to parent) or `merge: false` (replace entirely).
|
||||
- server-level `config.yml`
|
||||
- project-level `api/config.yml`
|
||||
- collection/action-level YAML overrides
|
||||
|
||||
For a project that serves a browser-based SPA to end users on its own domain and serves API/tibiadmin on separate subdomains, the default (no explicit CORS config) is usually correct since the SPA makes same-origin API calls via the BrowserSync/production reverse proxy. Add explicit CORS only when:
|
||||
- the API is called from external origins (e.g. third-party integrations)
|
||||
- the admin UI is served on a different origin than the API
|
||||
- an action endpoint needs to support cross-origin form submissions
|
||||
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.
|
||||
|
||||
See `tibi-server/docs/02-configuration.md` (section "CORS Configuration Hierarchy") for details.
|
||||
## Recommended implementation patterns
|
||||
|
||||
## Secure implementation patterns
|
||||
|
||||
### Public form endpoint
|
||||
### Public form workflow
|
||||
|
||||
Recommended shape:
|
||||
|
||||
- public action with narrow allowed methods
|
||||
- public action with narrow methods
|
||||
- server-side validation
|
||||
- no broad admin tokens in the browser
|
||||
- no unnecessary collection write permissions exposed publicly
|
||||
- no admin token in the browser
|
||||
- separate internal persistence only when truly required
|
||||
|
||||
### Integration token
|
||||
|
||||
@@ -162,32 +211,42 @@ Recommended shape:
|
||||
- minimal collection/action scope
|
||||
- header-based transport preferred
|
||||
|
||||
### Hook that calls external services
|
||||
### Sensitive internal fields
|
||||
|
||||
Recommended shape:
|
||||
|
||||
- fixed or validated destination URLs
|
||||
- no arbitrary user-controlled internal target fetching
|
||||
- minimal capability needed for the feature
|
||||
- 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
|
||||
- Using admin tokens for routine frontend or integration traffic
|
||||
- Enabling bulk write permissions without a strong operational reason
|
||||
- Treating hook `http.fetch` and `exec.command` as risk-free utilities
|
||||
- Solving access control in the UI instead of on the server
|
||||
- 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. Public endpoints expose only the required methods.
|
||||
5. Risky hook capabilities are constrained by design.
|
||||
6. `yarn validate` stays clean.
|
||||
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
|
||||
|
||||
@@ -195,8 +254,9 @@ When asked to harden or design secure access on this starter, inspect in this or
|
||||
|
||||
1. `tibi-server/docs/05-authentication.md`
|
||||
2. `tibi-server/docs/14-security.md`
|
||||
3. the relevant collection/action permission sets
|
||||
4. secret sourcing in config/env
|
||||
5. whether hooks use risky capabilities like outbound fetch or exec
|
||||
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.
|
||||
This prevents working implementations that quietly widen the attack surface.
|
||||
|
||||
Reference in New Issue
Block a user