fc security
npm install fc-securityfc-auth package.
typescript
const securityMiddleware = new SecurityMiddleware({
// Health check paths that bypass all security
healthCheckPaths: ['/health', '/api/health', '/monitoring/ping'],
cors: {
origin: ['*.yourcompany.com', 'null'], // "null" allows no-origin requests
},
// ... other security config
});
`
$3
Skip security validation for specific fields or entire URL patterns:
`typescript
const securityMiddleware = new SecurityMiddleware({
// Skip security checks for sensitive fields that might contain special characters
skipFields: [
'password', // Password fields
'token', // Auth tokens
'secret', // API secrets
'apiKey', // API keys
'privateKey' // Private keys
],
// Skip all security checks for specific URL patterns
skipUrls: [
'/auth/login', // Exact URL match
'/api/public/*', // Wildcard pattern
'/upload/*', // File upload endpoints
'/webhooks/*' // Webhook endpoints
],
// ... other security config
});
`
Use Cases for Field Skipping:
- Passwords: May contain SQL-like patterns or special characters
- API Keys: Often contain encoded data that triggers false positives
- Encrypted Data: Base64 or hex-encoded content may appear malicious
- Binary Data: File uploads or binary content encoded as strings
Use Cases for URL Skipping:
- Authentication Endpoints: Login/register forms with sensitive data
- File Upload Endpoints: Binary data that may trigger security alerts
- Public APIs: Endpoints that need to accept any content
- Webhook Endpoints: External integrations with unpredictable payloads
$3
You can now selectively enable or disable security modules by setting enabled: false in their configuration:
`typescript
const securityMiddleware = new SecurityMiddleware({
cors: {
enabled: false, // Completely disable CORS handling
},
validation: {
enabled: true, // Keep input validation enabled
strictMode: false,
},
headers: {
enabled: false, // Disable security headers
},
sqlInjection: {
enabled: true, // Keep SQL injection protection
strictMode: true,
},
xss: {
enabled: false, // Disable XSS protection
},
fileUpload: {
enabled: false, // File upload validation is disabled by default
},
});
`
Benefits:
- Performance: Disabled modules are completely bypassed, improving performance
- Flexibility: Enable only the security features you need
- Environment-specific: Different configurations for dev, staging, and production
- Backwards Compatible: All modules are enabled by default (except file upload)
$3
Control what error messages are sent to clients when security violations occur:
`typescript
const securityMiddleware = new SecurityMiddleware({
errorResponse: {
// Send detailed errors (useful for testing/debugging)
exposeDetailedErrors: process.env.NODE_ENV === 'development',
// Custom message when detailed errors are disabled
customErrorMessage: 'Request blocked by security policy',
},
logging: {
enabled: true,
logLevel: 'info',
},
});
`
Error Response Examples:
`javascript
// When exposeDetailedErrors: true (development/testing)
{
"error": "Security Violation",
"message": "Potential SQL injection detected in query parameter (pattern: UNION SELECT)",
"timestamp": "2025-08-14T10:30:00.000Z",
"requestId": "sec_1692012600000_abc123",
"details": {
"errorType": "SQL_INJECTION",
"severity": "HIGH"
}
}
// When exposeDetailedErrors: false (production)
{
"error": "Security Violation",
"message": "Request blocked by security policy",
"timestamp": "2025-08-14T10:30:00.000Z",
"requestId": "sec_1692012600000_abc123"
}
`
Use Cases:
- Testing: Enable detailed errors for end-to-end test validation
- Development: Show specific security violations for debugging
- Production: Generic messages to avoid information disclosure
- Custom Messages: Branded or user-friendly error messages
For detailed documentation, see HEALTH_CHECK_CONFIGURATION.md and SECURITY_README.md.
Basic Usage
$3
TimerProvider is automatically bound to your Application's
Context using the LogComponent
which exports this provider with a binding key of extension-starter.timer. You
can learn more about components in the
related resources section.
This provider makes available to your application a timer function which given a
start time _(given as an array [seconds, nanoseconds])_ can give you a total
time elapsed since the start in milliseconds. The timer can also start timing if
no start time is given. This is used by LogComponent to allow a user to time a
Sequence.
_NOTE:_ _You can get the start time in the required format by using
this.logger.startTimer()._
You can provide your own implementation of the elapsed time function by binding
it to the binding key (accessible via ExtensionStarterBindings) as follows:
`ts
app.bind(ExtensionStarterBindings.TIMER).to(timerFn);
`
$3
LogProvider can automatically be bound to your Application's Context using the
LogComponent which exports the provider with a binding key of
extension-starter.actions.log.
The key can be accessed by importing ExtensionStarterBindings as follows:
Example: Binding Keys
`ts
import {ExtensionStarterBindings} from 'HelloExtensions';
// Key can be accessed as follows now
const key = ExtensionStarterBindings.LOG_ACTION;
`
LogProvider gives us a sequence action and a startTimer function. In order to
use the sequence action, you must define your own sequence as shown below.
Example: Sequence
`ts
class LogSequence implements SequenceHandler {
constructor(
@inject(coreSequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
@inject(coreSequenceActions.PARSE_PARAMS)
protected parseParams: ParseParams,
@inject(coreSequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
@inject(coreSequenceActions.SEND) protected send: Send,
@inject(coreSequenceActions.REJECT) protected reject: Reject,
// We get the logger injected by the LogProvider here
@inject(ExtensionStarterBindings.LOG_ACTION) protected logger: LogFn,
) {}
async handle(context: RequestContext) {
const {request, response} = context;
// We define these variable outside so they can be accessed by logger.
let args: any = [];
let result: any;
// Optionally start timing the sequence using the timer
// function available via LogFn
const start = this.logger.startTimer();
try {
const route = this.findRoute(request);
args = await this.parseParams(request, route);
result = await this.invoke(route, args);
this.send(response, result);
} catch (error) {
result = error; // so we can log the error message in the logger
this.reject(context, error);
}
// We call the logger function given to us by LogProvider
this.logger(request, args, result, start);
}
}
`
Once a sequence has been written, we can just use that in our Application as
follows:
Example: Application
`ts
const app = new Application({
sequence: LogSequence,
});
app.component(LogComponent);
// Now all requests handled by our sequence will be logged.
``