Data classification levels (Public, Internal, Confidential, Restricted) and handling requirements per Hack23 Data Classification Policy
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:
Edit PDFs with natural-language instructions using the nano-pdf CLI.
Control Sonos speakers (discover/status/play/volume/group).
Terminal Spotify playback/search via spogo (preferred) or spotify_player.
Capture frames or clips from RTSP/ONVIF cameras.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
Monitor blogs and RSS/Atom feeds for updates using the blogwatcher CLI.
Category:tools