mit einem Klick
data-classification
// Data classification levels (Public, Internal, Confidential, Restricted) and handling requirements per Hack23 Data Classification Policy
// Data classification levels (Public, Internal, Confidential, Restricted) and handling requirements per Hack23 Data Classification Policy
GitHub Agentic Workflows (gh-aw) - markdown-based AI automation with 5-layer security, safe outputs, and Continuous AI patterns
gh-aw CLI usage, compilation, testing, debugging, add-wizard, and CI/CD practices for GitHub Agentic Workflows
Multi-agent coordination, orchestrator-worker patterns, /plan decomposition, and project coordination for GitHub Agentic Workflows
5-layer defense-in-depth security for GitHub Agentic Workflows - safe outputs, threat detection, AWF firewall, and zero-trust patterns
Continuous AI patterns from Agent Factory - issue triage, documentation sync, code quality, security scanning, and project coordination
GDPR compliance including privacy by design, data protection requirements, consent management, right to be forgotten, and data breach response
| name | data-classification |
| description | Data classification levels (Public, Internal, Confidential, Restricted) and handling requirements per Hack23 Data Classification Policy |
| license | Apache-2.0 |
This skill implements data classification requirements as defined in the Hack23 ISMS Data Classification Policy. It ensures that all data is properly classified and handled according to its sensitivity level.
Hack23 uses four classification levels:
Definition: Information that can be freely disclosed to the public without harm to Hack23, customers, or partners.
Examples:
MUST:
MUST NOT:
Definition: Information for use within Hack23 that should not be publicly disclosed but is not highly sensitive.
Examples:
MUST:
MUST NOT:
Definition: Sensitive information that could cause significant harm if disclosed.
Examples:
MUST:
MUST NOT:
Definition: Highly sensitive information that could cause severe harm if disclosed.
Examples:
MUST:
MUST NOT:
| Requirement | PUBLIC | INTERNAL | CONFIDENTIAL | RESTRICTED |
|---|---|---|---|---|
| Authentication | Not required | Required | Required | MFA required |
| Access Control | Open | RBAC | Strict RBAC | Strict RBAC + approval |
| Encryption at Rest | Optional | Recommended | Required (AES-256) | Required (AES-256) |
| Encryption in Transit | Recommended | Required (TLS 1.2+) | Required (TLS 1.2+) | Required (TLS 1.2+) |
| Access Logging | Optional | Recommended | Required | Required + monitoring |
| Access Review | N/A | Annually | Quarterly | Monthly |
| Backup | Standard | Standard | Encrypted backup | Encrypted backup |
| Retention | As needed | Per policy | Strict policy | Immediate deletion |
| External Sharing | Allowed | With approval | NDA required | Prohibited |
MUST:
MUST NOT:
PUBLIC:
INTERNAL:
CONFIDENTIAL:
RESTRICTED:
PUBLIC:
INTERNAL:
CONFIDENTIAL:
RESTRICTED:
PUBLIC:
INTERNAL:
CONFIDENTIAL:
RESTRICTED:
<!-- PUBLIC data -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="classification" content="PUBLIC">
<title>Hack23 - Cybersecurity Consulting</title>
</head>
<!-- INTERNAL data -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="classification" content="INTERNAL">
<meta name="robots" content="noindex, nofollow">
<title>Internal Project Documentation</title>
</head>
// Define classification metadata
const userSchema = new mongoose.Schema({
// PUBLIC
username: {
type: String,
classification: 'PUBLIC',
required: true
},
// INTERNAL
email: {
type: String,
classification: 'INTERNAL',
required: true
},
// CONFIDENTIAL
firstName: {
type: String,
classification: 'CONFIDENTIAL',
required: true
},
lastName: {
type: String,
classification: 'CONFIDENTIAL',
required: true
},
dateOfBirth: {
type: Date,
classification: 'CONFIDENTIAL'
},
// RESTRICTED
passwordHash: {
type: String,
classification: 'RESTRICTED',
required: true,
select: false // Never return in queries by default
},
ssn: {
type: String,
classification: 'RESTRICTED',
select: false,
// Encrypt at application level before storage
get: (value) => decrypt(value),
set: (value) => encrypt(value)
}
});
const winston = require('winston');
// Create logger with classification filter
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'application.log' })
]
});
// Safe logging helper
function logSafely(level, message, metadata = {}) {
// Filter out sensitive data
const safeMetadata = {};
for (const [key, value] of Object.entries(metadata)) {
const classification = value?.classification || 'INTERNAL';
// NEVER log RESTRICTED data
if (classification === 'RESTRICTED') {
safeMetadata[key] = '[RESTRICTED - REDACTED]';
}
// Mask CONFIDENTIAL data
else if (classification === 'CONFIDENTIAL') {
safeMetadata[key] = maskConfidential(value);
}
// INTERNAL and PUBLIC can be logged
else {
safeMetadata[key] = value;
}
}
logger.log(level, message, safeMetadata);
}
function maskConfidential(value) {
if (typeof value === 'string' && value.length > 4) {
return value.substring(0, 2) + '***' + value.substring(value.length - 2);
}
return '***';
}
// Usage
logSafely('info', 'User login', {
username: { value: 'john_doe', classification: 'PUBLIC' },
email: { value: 'john@example.com', classification: 'INTERNAL' },
ipAddress: { value: '192.168.1.1', classification: 'INTERNAL' },
password: { value: 'secretpassword', classification: 'RESTRICTED' } // Will be redacted
});
// Output: { username: 'john_doe', email: 'john@example.com', ipAddress: '192.168.1.1', password: '[RESTRICTED - REDACTED]' }
// Filter API responses based on user permissions and classification
function filterResponseByClassification(data, userRole) {
// Define role clearance levels
const clearanceLevels = {
'public': ['PUBLIC'],
'user': ['PUBLIC', 'INTERNAL'],
'admin': ['PUBLIC', 'INTERNAL', 'CONFIDENTIAL']
// RESTRICTED data is never included in API responses
};
const allowedClassifications = clearanceLevels[userRole] || ['PUBLIC'];
const filtered = {};
for (const [key, value] of Object.entries(data)) {
const classification = value?.classification || 'INTERNAL';
if (classification === 'RESTRICTED') {
// Never include RESTRICTED data in API responses
continue;
}
if (allowedClassifications.includes(classification)) {
filtered[key] = value.data || value;
}
}
return filtered;
}
// Usage
app.get('/api/user/:id', requireAuth, async (req, res) => {
const user = await db.users.findById(req.params.id);
const userData = {
username: { data: user.username, classification: 'PUBLIC' },
email: { data: user.email, classification: 'INTERNAL' },
firstName: { data: user.firstName, classification: 'CONFIDENTIAL' },
lastName: { data: user.lastName, classification: 'CONFIDENTIAL' },
ssn: { data: user.ssn, classification: 'RESTRICTED' } // Will never be included
};
const filtered = filterResponseByClassification(userData, req.user.role);
res.json(filtered);
});
const fs = require('fs');
const xattr = require('fs-xattr');
// Set classification on file using extended attributes
async function setFileClassification(filePath, classification) {
const validClassifications = ['PUBLIC', 'INTERNAL', 'CONFIDENTIAL', 'RESTRICTED'];
if (!validClassifications.includes(classification)) {
throw new Error(`Invalid classification: ${classification}`);
}
// Set extended attribute
await xattr.set(filePath, 'user.classification', classification);
// Set appropriate file permissions
const permissions = {
'PUBLIC': 0o644, // rw-r--r--
'INTERNAL': 0o640, // rw-r-----
'CONFIDENTIAL': 0o600, // rw-------
'RESTRICTED': 0o600 // rw-------
};
await fs.promises.chmod(filePath, permissions[classification]);
}
// Get file classification
async function getFileClassification(filePath) {
try {
return await xattr.get(filePath, 'user.classification');
} catch (err) {
return 'INTERNAL'; // Default classification
}
}
// Verify file handling based on classification
async function verifyFileHandling(filePath) {
const classification = await getFileClassification(filePath);
switch (classification) {
case 'RESTRICTED':
case 'CONFIDENTIAL':
// Verify encryption
const encrypted = await isFileEncrypted(filePath);
if (!encrypted) {
throw new Error(`${classification} file must be encrypted: ${filePath}`);
}
break;
case 'INTERNAL':
// Verify access controls
const stats = await fs.promises.stat(filePath);
if (stats.mode & 0o004) { // World readable
throw new Error(`INTERNAL file must not be world-readable: ${filePath}`);
}
break;
}
}
const crypto = require('crypto');
const fs = require('fs').promises;
async function secureDelete(filePath, classification) {
const stats = await fs.stat(filePath);
const fileSize = stats.size;
switch (classification) {
case 'PUBLIC':
case 'INTERNAL':
// Simple deletion
await fs.unlink(filePath);
break;
case 'CONFIDENTIAL':
// Overwrite with random data 3 times
for (let i = 0; i < 3; i++) {
const randomData = crypto.randomBytes(fileSize);
await fs.writeFile(filePath, randomData);
}
// Then delete
await fs.unlink(filePath);
break;
case 'RESTRICTED':
// Overwrite with random data 7 times (DoD 5220.22-M standard)
for (let i = 0; i < 7; i++) {
const randomData = crypto.randomBytes(fileSize);
await fs.writeFile(filePath, randomData);
// Sync to ensure write to disk
const fd = await fs.open(filePath, 'r+');
await fd.sync();
await fd.close();
}
// Final overwrite with zeros
await fs.writeFile(filePath, Buffer.alloc(fileSize, 0));
// Then delete
await fs.unlink(filePath);
break;
}
// Log secure deletion
logger.info('Secure deletion completed', {
file: filePath,
classification: classification,
timestamp: new Date().toISOString()
});
}
All data MUST be classified. Violations: