My solutions for CTFs
0

Configure Feed

Select the types of activity you want to include in your feed.

fix: Delete CognitiveHack files

Takumi Akimoto (May 17, 2026, 4:49 PM +0900) f0e8a21b 8e1acb06

-1113
-193
cognitivehack/2026/fool-the-lockout/app.py
··· 1 - from flask import Flask, render_template, request, redirect, url_for, session, make_response 2 - import time 3 - import secrets 4 - import json 5 - 6 - 7 - app = Flask(__name__) 8 - app.secret_key = secrets.token_hex(16) 9 - 10 - user_db = {} 11 - """ format -> 12 - username: "password" 13 - } 14 - """ 15 - 16 - request_rates = {} 17 - """ format -> 18 - "ip_addr":{ 19 - "num_requests": int 20 - "epoch_start": timestamp 21 - "lockout_until" : int # -1 if not locked out, timestamp of lockout end 22 - } 23 - """ 24 - 25 - MAX_REQUESTS = 10 # max failed attempts before a user is locked out 26 - EPOCH_DURATION = 30 # timeframe for failed attempts (in seconds) 27 - LOCKOUT_DURATION = 120 # duration a user will be locked out for (in seconds) 28 - 29 - RATE_LIMITED_HTML = "<h1>Rate Limited Exceeded</h1><p>You have sent too many requests, requests from your IP will be temporarily blocked.</p>" 30 - 31 - 32 - 33 - ## ------------------------ HELPER FUNCTIONS ------------------------ ## 34 - 35 - """Quick function to no-cache web page responses""" 36 - def no_cache(response): 37 - response.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0" 38 - response.headers["Pragma"] = "no-cache" 39 - response.headers["Expires"] = "-1" 40 - return response 41 - 42 - 43 - """Returns true if a user is logged in, false otherwise""" 44 - def logged_in(): 45 - if "user" in session: 46 - return True 47 - return False 48 - 49 - 50 - """Returns the current user (or None if there is none)""" 51 - def current_user(): 52 - if "user" in session: 53 - return session["user"] 54 - return None 55 - 56 - 57 - """Add a new user to db""" 58 - def add_new_user(username, password): 59 - user_db[username] = password 60 - print("Added (username=%s, password=%s) to user_db" % (username, password)) 61 - 62 - 63 - """ Updates the request rates db for a given client ip, since information will likely be stale.""" 64 - def refresh_request_rates_db(client_ip): 65 - curr_time = time.time() 66 - if client_ip not in request_rates: 67 - return 68 - 69 - # check if attempt interval has elapsed, if so sets it to 0 70 - epoch_start_time = request_rates[client_ip]["epoch_start"] 71 - if curr_time - epoch_start_time > EPOCH_DURATION: 72 - request_rates[client_ip]["num_requests"] = 0 73 - request_rates[client_ip]["epoch_start"] = -1 74 - 75 - # if was locked out but period ended update store 76 - lockout_end = request_rates[client_ip]["lockout_until"] 77 - if (lockout_end != -1) and time.time() >= lockout_end: 78 - request_rates[client_ip]["lockout_until"] = -1 79 - 80 - 81 - """For a given user IP, checks how many requests the user has made (by updating the storage) and if 82 - the user it has exceeded the assigned rate limit. Returns true if the user has exceeded rate limit, 83 - false otherwise. """ 84 - def exceeded_rate_limit() -> bool: # Could do a daemon, but since checks of status are always done before updating its not really necessary 85 - curr_time = time.time() 86 - 87 - # Grab the IP of the client 88 - client_ip = request.remote_addr 89 - print(f"Request ip address: {client_ip}", flush=True) 90 - 91 - # refresh & add new entry to db if it doesnt exist 92 - refresh_request_rates_db(client_ip) 93 - if client_ip not in request_rates: 94 - request_rates[client_ip] = { 95 - "num_requests": 0, 96 - "epoch_start": -1, 97 - "lockout_until": -1 98 - } 99 - print(f"New entry added to db", flush=True) 100 - 101 - # log request if it was a POST 102 - if request.method == "POST": 103 - request_rates[client_ip]['num_requests'] += 1 104 - # if epoch hasnt started, set epoch 105 - if request_rates[client_ip]['epoch_start'] == -1: 106 - request_rates[client_ip]['epoch_start'] = curr_time 107 - print(f"DB updated - {client_ip}:{request_rates[client_ip]}", flush=True) 108 - 109 - # check if we exceeded rate threshold, return True if so 110 - if request_rates[client_ip]['num_requests'] > MAX_REQUESTS: 111 - if request_rates[client_ip]["lockout_until"] == -1: 112 - request_rates[client_ip]['lockout_until'] = curr_time + LOCKOUT_DURATION 113 - print("Account locked out") 114 - print(f"DB - {client_ip}:{request_rates[client_ip]}", flush=True) 115 - return True 116 - 117 - return False 118 - 119 - 120 - ## ------------------------ APP ROUTES ------------------------ ## 121 - 122 - """ Login portal """ 123 - @app.route("/login", methods=['GET', 'POST']) 124 - def login(): 125 - ## TODO - check rate limit 126 - if exceeded_rate_limit(): 127 - return RATE_LIMITED_HTML 128 - 129 - # if POST, accept form data and try to add user 130 - if request.method == "POST": 131 - user_input = request.form['username'] 132 - pswd_input = request.form['password'] 133 - print("User input: %s, password input: %s" % (user_input, pswd_input)) 134 - 135 - # non-existent user or bad password 136 - if (user_input not in user_db) or (user_db[user_input] != pswd_input): 137 - msg = f"Invalid username or password." 138 - return render_template("login.html", error=msg) 139 - 140 - # authenticate user 141 - session["user"] = user_input 142 - print("Successfully logged in, session=%s" % (session)) 143 - return redirect(url_for("index")) # note 'index' refers to the FUNCTION NAME 144 - 145 - # return normal page if 'GET' 146 - return no_cache(make_response(render_template('login.html'))) 147 - 148 - 149 - """ Homepage """ 150 - @app.route("/", methods=['GET']) 151 - def index(): 152 - if exceeded_rate_limit(): 153 - return RATE_LIMITED_HTML 154 - 155 - # authenticate 156 - if not logged_in(): 157 - return redirect(url_for("login")) 158 - 159 - # display homepage according to login 160 - user = current_user() 161 - flag = open("/challenge/flag.txt").read().strip() 162 - return no_cache(make_response(render_template("index.html", user=user, flag=flag))) 163 - 164 - 165 - """ Logout """ 166 - @app.route("/logout", methods=['GET']) 167 - def logout(): 168 - if exceeded_rate_limit(): 169 - return RATE_LIMITED_HTML 170 - 171 - if "user" in session: 172 - session.pop('user', None) 173 - print("Logged out, popped session") 174 - return redirect(url_for("login")) 175 - 176 - 177 - if __name__ == '__main__': 178 - username, password = None, None 179 - # get profile data 180 - try: 181 - with open("/challenge/profile.json", "r") as file: 182 - profile = json.load(file) 183 - username = profile["username"] 184 - password = profile["password"] 185 - except Exception as e: 186 - print(f"Error setting up profile in app:\n{e}") 187 - exit(1) 188 - 189 - # add new user 190 - add_new_user(username, password) 191 - 192 - # start app 193 - app.run(host='0.0.0.0', port=8000, debug=True)
-100
cognitivehack/2026/fool-the-lockout/creds-dump.txt
··· 1 - rora;winner1 2 - birendra;rumble 3 - khalid;sting 4 - stanislaw;ming 5 - maged;nimrod 6 - sigrid;telephon 7 - alysse;sutton 8 - emely;tyrant 9 - cornel;rodman 10 - shamira;marion 11 - cymbre;california 12 - romola;steven 13 - leisa;basketba 14 - goldie;ferrari 15 - celia;beatles 16 - kathrine;tango 17 - adrianne;iiiiii 18 - rebbecca;core 19 - meridel;bolton 20 - riva;trent 21 - dorris;sponge 22 - ngai;ellie 23 - gwynn;grizzly 24 - olenka;london1 25 - vahe;devilman 26 - germ;bigguns 27 - bradwin;doogie 28 - marinette;pic\'s 29 - kori;swimming 30 - leita;4you 31 - arzu;calimero 32 - roanna;trooper1 33 - meena;tracy 34 - beryle;zippy 35 - field;sunflowe 36 - keaton;hall 37 - amandine;whatup 38 - cherise;dean 39 - aidan;gallaries 40 - medria;locutus 41 - marga;infinite 42 - triston;kristina 43 - ljilyana;carsten 44 - paulo;chicks 45 - woodrow;14141414 46 - dacie;diamond1 47 - evy;sex4me 48 - amabelle;fatty 49 - technical;market 50 - celesta;drive 51 - sherill;icecube 52 - nadir;vides 53 - ayesha;necklace 54 - dolorita;concorde 55 - linnet;yaya 56 - clareta;yankee1 57 - colm;goblue 58 - felton;divine 59 - tera;mccabe 60 - bethan;barber 61 - rohit;berry 62 - cali;assword 63 - faina;choke 64 - saleem;ella 65 - luelle;bolitas 66 - emmey;spanner 67 - carlyn;kokoko 68 - sallyanne;mordor 69 - my;hotsex 70 - constantia;budlight 71 - tenille;lambert 72 - suria;james007 73 - princeton;olympic 74 - goska;allan 75 - joana;citroen 76 - deane;shoe 77 - brynna;church 78 - oliver;higgins 79 - erinn;nineinch 80 - val;sampson 81 - duquette;5252 82 - sieber;ripple 83 - danice;smooth 84 - romonda;texaco 85 - sinead;infiniti 86 - linette;reddog 87 - almendra;christin 88 - meriann;kajak 89 - shedman;ewtosi 90 - elody;athome 91 - doloritas;birgit 92 - cecile;makaveli 93 - arielle;rachel 94 - mitch;killers 95 - henrietta;egghead 96 - sule;devon 97 - huan-yu;destin 98 - lita;2277 99 - ravi;969696 100 - percy;puddin
-25
cognitivehack/2026/secret-box/docker-compose.yml
··· 1 - services: 2 - app: 3 - build: 4 - context: ./app 5 - ports: 6 - - "8080:80" 7 - depends_on: 8 - - db 9 - restart: always 10 - environment: 11 - USERPASSWORD: password 12 - FLAG: picoCTF{fake_flag} 13 - DB_HOST: db 14 - DB_USER: postgres 15 - DB_PASSWORD: password 16 - DB_NAME: secretbox 17 - DB_PORT: 5432 18 - db: 19 - build: ./db 20 - environment: 21 - POSTGRES_USER: postgres 22 - POSTGRES_PASSWORD: password 23 - POSTGRES_DB: secretbox 24 - ports: 25 - - "5432:5432"
-28
cognitivehack/2026/secret-box/app/Dockerfile
··· 1 - FROM node:18@sha256:5381bf8dd7e1dc53350b921f02811bd9167b34d3f7d0d8ebcc28229f65aef035 AS base 2 - 3 - # Set up challenge directory 4 - WORKDIR /challenge 5 - 6 - # install packages 7 - RUN npm install --no-package-lock \ 8 - express \ 9 - ejs \ 10 - dotenv \ 11 - pg \ 12 - knex 13 - 14 - # Copy only the source code 15 - COPY src/ ./src/ 16 - 17 - # Specify a new stage for the challenge. Everything previous to this can be 18 - # reused for every instance. 19 - FROM base AS challenge 20 - # Bring in FLAG from cmgr. Busts the cache every time. 21 - ARG FLAG 22 - 23 - # Open up this port for the web server 24 - EXPOSE 80 25 - 26 - CMD node /challenge/src/server.js 27 - 28 -
-2
cognitivehack/2026/secret-box/db/Dockerfile
··· 1 - FROM postgres@sha256:301bcb60b8a3ee4ab7e147932723e3abd1cef53516ce5210b39fd9fe5e3602ae 2 - COPY initdb.sql /docker-entrypoint-initdb.d/
-26
cognitivehack/2026/secret-box/db/initdb.sql
··· 1 - CREATE EXTENSION IF NOT EXISTS pgcrypto; 2 - 3 - CREATE TABLE users ( 4 - id text PRIMARY KEY DEFAULT gen_random_uuid(), 5 - username text NOT NULL, 6 - password text NOT NULL, 7 - created_at timestamptz NOT NULL DEFAULT now() 8 - ); 9 - 10 - CREATE TABLE tokens ( 11 - id text PRIMARY KEY DEFAULT gen_random_uuid(), 12 - user_id text NOT NULL REFERENCES users(id), 13 - created_at timestamptz NOT NULL DEFAULT now(), 14 - expired_at timestamptz NOT NULL DEFAULT now() + interval '1 days' 15 - ); 16 - 17 - CREATE TABLE secrets ( 18 - id text PRIMARY KEY DEFAULT gen_random_uuid(), 19 - owner_id text NOT NULL REFERENCES users(id), 20 - content text NOT NULL, 21 - created_at timestamptz NOT NULL DEFAULT now() 22 - ); 23 - 24 - 25 - INSERT INTO users(id, username, password) VALUES ('e2a66f7d-2ce6-4861-b4aa-be8e069601cb', 'admin', 'fake_password'); 26 - INSERT INTO secrets(owner_id, content) VALUES ('e2a66f7d-2ce6-4861-b4aa-be8e069601cb', 'picoCTF{fake_flag}');
-40
cognitivehack/2026/secret-box/app/src/db.js
··· 1 - const path = require('path'); 2 - require('dotenv').config({ path: path.join(__dirname, '.env') }); 3 - 4 - const knex = require('knex'); 5 - 6 - const db = knex({ 7 - client: 'pg', 8 - connection: { 9 - host: process.env.DB_HOST, 10 - port: process.env.DB_PORT, 11 - user: process.env.DB_USER, 12 - password: process.env.DB_PASSWORD, 13 - database: process.env.DB_NAME, 14 - }, 15 - pool: {min: 0, max: 5}, 16 - }); 17 - 18 - 19 - async function initdb() { 20 - try { 21 - console.log("Testing DB connection..."); 22 - await db.raw('SELECT 1'); 23 - console.log('Database connection successful'); 24 - 25 - await db('users') 26 - .where({ id: 'e2a66f7d-2ce6-4861-b4aa-be8e069601cb' }) 27 - .update({ password: process.env.USERPASSWORD }); 28 - 29 - await db('secrets') 30 - .where({ owner_id: 'e2a66f7d-2ce6-4861-b4aa-be8e069601cb' }) 31 - .update({ content: process.env.FLAG }); 32 - 33 - console.log("Real flag and password updated"); 34 - } catch (error) { 35 - console.error('Database connection failed:', error.message); 36 - process.exit(1); 37 - } 38 - } 39 - 40 - module.exports = { db, initdb };
-41
cognitivehack/2026/secret-box/app/src/handler.js
··· 1 - const { db } = require('./db'); 2 - 3 - // token hanlder 4 - const getCookies = (cookieHeader) => { 5 - if (!cookieHeader) return {}; 6 - return Object.fromEntries( 7 - cookieHeader.split(';').map(cookie => { 8 - const [key, ...value] = cookie.trim().split('='); 9 - return [key, decodeURIComponent(value.join('='))]; 10 - }) 11 - ); 12 - }; 13 - 14 - const authMiddleware = async (req, res, next) => { 15 - const cookies = getCookies(req.headers.cookie); 16 - const token = cookies.auth_token; 17 - 18 - if (!token) { return next(); } 19 - 20 - try { 21 - const query = await db.raw( 22 - `SELECT * FROM tokens WHERE id = ? AND expired_at > NOW()`, 23 - [token] 24 - ); 25 - 26 - if(query.rows.length <= 0) { 27 - res.clearCookie('auth_token'); 28 - return res.render('index', {message: null, error: 'Invalid or expired token'}); 29 - } 30 - 31 - // valid token 32 - req.userId = query.rows[0].user_id; 33 - return next() 34 - } catch (err){ 35 - res.clearCookie('auth_token'); 36 - console.log(`Server Internal Error: ${err}`) 37 - return res.render('index', {message: null, error: `Server Internal Error`}); 38 - } 39 - }; 40 - 41 - module.exports = authMiddleware;
-145
cognitivehack/2026/secret-box/app/src/server.js
··· 1 - const express = require('express'); 2 - const app = express(); 3 - const fs = require('fs'); 4 - const path = require('path'); 5 - const PORT = process.env.PORT || 80; 6 - 7 - const { db, initdb } = require('./db'); 8 - const authMiddleware = require('./handler'); 9 - 10 - 11 - // Parse JSON bodies 12 - app.use(express.json()); 13 - app.use(express.urlencoded({ extended: true })); 14 - 15 - 16 - // Set up EJS as the view engine 17 - app.set('view engine', 'ejs'); 18 - app.set('views', path.join(__dirname, 'views')); 19 - 20 - 21 - // GET index page 22 - app.get('/', authMiddleware, async (req, res) => { 23 - const userId = req.userId; 24 - 25 - if (userId){ 26 - // logged in 27 - const query = await db.raw( 28 - `SELECT * FROM secrets WHERE owner_id = ?`, 29 - [userId] 30 - ); 31 - 32 - return res.render('my_secrets', {secrets: query.rows}); 33 - } 34 - else { 35 - // if not yet login 36 - return res.render('index', {message: null, error: null}); 37 - } 38 - }); 39 - 40 - // GET login page 41 - app.get('/login', (req, res) => { 42 - return res.render('login', {message: null, error: null}); 43 - }); 44 - 45 - // GET signup page 46 - app.get('/signup', (req, res) => { 47 - return res.render('signup', {message: null, error: null}); 48 - }); 49 - 50 - // GET create new secret page 51 - app.get('/secrets/create', authMiddleware, (req, res) => { 52 - return res.render('create_secret'); 53 - }); 54 - 55 - // POST login 56 - app.post('/login', async (req, res) => { 57 - const { username, password} = req.body; 58 - 59 - const userResult = await db.raw( 60 - `SELECT * FROM users WHERE username = ? AND password = ? LIMIT 1`, 61 - [username, password] 62 - ); 63 - 64 - // check user 65 - const user = userResult.rows[0]; 66 - if(!user){ 67 - return res.render('login', {message: null, error: 'User Not Found or The password is wrong'}); 68 - } 69 - 70 - 71 - // check token 72 - const tokenQuery = await db.raw( 73 - `SELECT id FROM tokens WHERE user_id = ? AND expired_at > NOW()`, 74 - [user.id] 75 - ); 76 - 77 - let token = tokenQuery.rows[0]?.id; 78 - if(!token){ 79 - // no valid token: create one 80 - const createTokenQuery = await db.raw( 81 - `INSERT INTO tokens(user_id) VALUES (?) RETURNING id`, 82 - [user.id] 83 - ); 84 - 85 - token = createTokenQuery.rows[0].id; 86 - } 87 - 88 - res.cookie('auth_token', token); 89 - return res.redirect('/'); 90 - }); 91 - 92 - // POST signup 93 - app.post('/signup', async (req, res) => { 94 - const { username, password} = req.body; 95 - 96 - 97 - const userResult = await db.raw( 98 - `SELECT * FROM users WHERE username = ? LIMIT 1`, 99 - [username] 100 - ); 101 - 102 - if (userResult.rows.length >= 1){ 103 - // user exist 104 - return res.render('signup', {message: null, error: 'Username already exists'}); 105 - } 106 - 107 - const createUserQuery = await db.raw( 108 - `INSERT INTO users(username, password) VALUES (?, ?)`, 109 - [username, password] 110 - ); 111 - 112 - // render to login page: create user only, not logging in automatically 113 - return res.render('login', {message: 'Create User Successful', error: null}); 114 - }); 115 - 116 - 117 - app.post('/logout', async (req, res) => { 118 - res.clearCookie('auth_token'); 119 - return res.redirect('/'); 120 - }); 121 - 122 - app.post('/secrets/create', authMiddleware, async (req, res) => { 123 - const userId = req.userId; 124 - if (!userId){ 125 - // if user didn't login, redirect to index page 126 - res.clearCookie('auth_token'); 127 - return res.redirect('/'); 128 - } 129 - 130 - const content = req.body.content; 131 - const query = await db.raw( 132 - `INSERT INTO secrets(owner_id, content) VALUES ('${userId}', '${content}')` 133 - ); 134 - 135 - return res.redirect('/'); 136 - }); 137 - 138 - (async () => { 139 - // Ensure DB is ready before server runs 140 - await initdb(); 141 - 142 - app.listen(PORT, ()=> { 143 - console.log(`Server running on port ${PORT}`) 144 - }); 145 - })();
-88
cognitivehack/2026/secret-box/app/src/views/create_secret.ejs
··· 1 - <html lang="en"> 2 - <head> 3 - <meta charset="UTF-8"> 4 - <title>Secrets Vault</title> 5 - <style> 6 - * { 7 - margin: 0; 8 - padding: 0; 9 - box-sizing: border-box; 10 - } 11 - 12 - body { 13 - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 14 - max-width: 1200px; 15 - margin: 0 auto; 16 - padding: 40px 20px; 17 - background-color: #f9f9f9; 18 - color: #2d3436; 19 - line-height: 1.6; 20 - } 21 - 22 - .container { 23 - padding: 40px; 24 - text-align: center; 25 - margin: 0 auto; 26 - } 27 - 28 - .description { 29 - font-size: 1.1rem; 30 - margin-bottom: 36px; 31 - color: #636e72; 32 - } 33 - 34 - form { 35 - max-width: 400px; 36 - margin: 0 auto; 37 - padding: 30px; 38 - border-radius: 12px; 39 - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1); 40 - text-align: left; 41 - } 42 - 43 - .input { 44 - width: 100%; 45 - padding: 12px 16px; 46 - margin-bottom: 20px; 47 - border-radius: 8px; 48 - font-size: 1rem; 49 - transition: all 0.3s ease; 50 - } 51 - 52 - .input:focus { 53 - border-color: #5649c0; 54 - box-shadow: 0 0 0 3px rgba(86, 73, 192, 0.2); 55 - } 56 - 57 - .button { 58 - display: block; 59 - width: 100%; 60 - padding: 14px 24px; 61 - text-align: center; 62 - border: none; 63 - border-radius: 8px; 64 - font-size: 1rem; 65 - font-weight: 600; 66 - text-decoration: none; 67 - transition: all 0.3s ease; 68 - text-transform: capitalize; 69 - background: #5649c0; 70 - color: white; 71 - cursor: pointer; 72 - margin-top: 10px; 73 - } 74 - </style> 75 - </head> 76 - <body> 77 - <div class="container"> 78 - <div class="description">Create A New Secret</div> 79 - 80 - <form method="POST" action="/secrets/create"> 81 - <label for="content">Content:</label> 82 - <textarea id="content" name="content" class="input"></textarea> 83 - 84 - <input type="submit" value="Submit" class="button"> 85 - </form> 86 - </div> 87 - </body> 88 - </html>
-98
cognitivehack/2026/secret-box/app/src/views/index.ejs
··· 1 - <!DOCTYPE html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8"> 5 - <title>Secrets Vault</title> 6 - <style> 7 - * { 8 - margin: 0; 9 - padding: 0; 10 - box-sizing: border-box; 11 - } 12 - 13 - body { 14 - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 15 - max-width: 1200px; 16 - margin: 0 auto; 17 - padding: 40px 20px; 18 - background-color: #f9f9f9; 19 - color: #2d3436; 20 - line-height: 1.6; 21 - } 22 - 23 - .container { 24 - padding: 40px; 25 - text-align: center; 26 - margin: 0 auto; 27 - } 28 - 29 - h1 { 30 - color: #6c5ce7; 31 - margin-bottom: 24px; 32 - font-size: 2.5rem; 33 - font-weight: 700; 34 - } 35 - 36 - .highlight { 37 - font-size: 1.2rem; 38 - margin-bottom: 12px; 39 - font-weight: 600; 40 - } 41 - 42 - .description { 43 - font-size: 1.1rem; 44 - margin-bottom: 36px; 45 - color: #636e72; 46 - } 47 - 48 - .buttons { 49 - display: flex; 50 - justify-content: center; 51 - gap: 24px; 52 - margin-top: 36px; 53 - } 54 - 55 - .button { 56 - display: inline-block; 57 - min-width: 140px; 58 - padding: 14px 24px; 59 - text-align: center; 60 - border-radius: 8px; 61 - font-size: 1rem; 62 - font-weight: 600; 63 - text-decoration: none; 64 - transition: all 0.3s ease; 65 - text-transform: capitalize; 66 - background: #5649c0; 67 - color: white; 68 - } 69 - 70 - .vault-icon { 71 - font-size: 3rem; 72 - margin-bottom: 16px; 73 - } 74 - </style> 75 - </head> 76 - <body> 77 - <div class="container"> 78 - <% if (message) { %> 79 - <p style="color: green;"><%= message %></p> 80 - <% } %> 81 - 82 - <% if (error) { %> 83 - <p style="color: red;"><%= error %></p> 84 - <% } %> 85 - 86 - <div class="vault-icon">🔐</div> 87 - <h1>Secret Vault</h1> 88 - 89 - <div class="highlight">Carrying secrets that deserve a better hiding place?</div> 90 - <div class="description">Welcome to your personal vault - Only You Can See</div> 91 - 92 - <div class="buttons"> 93 - <a href="/login" class="button">Log In</a> 94 - <a href="/signup" class="button">Sign Up</a> 95 - </div> 96 - </div> 97 - </body> 98 - </html>
-100
cognitivehack/2026/secret-box/app/src/views/login.ejs
··· 1 - <!DOCTYPE html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8"> 5 - <title>Secrets Vault</title> 6 - <style> 7 - * { 8 - margin: 0; 9 - padding: 0; 10 - box-sizing: border-box; 11 - } 12 - 13 - body { 14 - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 15 - max-width: 1200px; 16 - margin: 0 auto; 17 - padding: 40px 20px; 18 - background-color: #f9f9f9; 19 - color: #2d3436; 20 - line-height: 1.6; 21 - } 22 - 23 - .container { 24 - padding: 40px; 25 - text-align: center; 26 - margin: 0 auto; 27 - } 28 - 29 - .description { 30 - font-size: 1.1rem; 31 - margin-bottom: 36px; 32 - color: #636e72; 33 - } 34 - 35 - form { 36 - max-width: 400px; 37 - margin: 0 auto; 38 - padding: 30px; 39 - border-radius: 12px; 40 - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1); 41 - text-align: left; 42 - } 43 - 44 - .input { 45 - width: 100%; 46 - padding: 12px 16px; 47 - margin-bottom: 20px; 48 - border-radius: 8px; 49 - font-size: 1rem; 50 - transition: all 0.3s ease; 51 - } 52 - 53 - .input:focus { 54 - border-color: #5649c0; 55 - box-shadow: 0 0 0 3px rgba(86, 73, 192, 0.2); 56 - } 57 - 58 - .button { 59 - display: block; 60 - width: 100%; 61 - padding: 14px 24px; 62 - text-align: center; 63 - border: none; 64 - border-radius: 8px; 65 - font-size: 1rem; 66 - font-weight: 600; 67 - text-decoration: none; 68 - transition: all 0.3s ease; 69 - text-transform: capitalize; 70 - background: #5649c0; 71 - color: white; 72 - cursor: pointer; 73 - margin-top: 10px; 74 - } 75 - </style> 76 - </head> 77 - <body> 78 - <div class="container"> 79 - <% if (message) { %> 80 - <p style="color: green;"><%= message %></p> 81 - <% } %> 82 - 83 - <% if (error) { %> 84 - <p style="color: red;"><%= error %></p> 85 - <% } %> 86 - 87 - <div class="description">Log In</div> 88 - 89 - <form method="POST" action="/login"> 90 - <label for="username">Name:</label> 91 - <input type="text" id="username" name="username" class="input"> 92 - 93 - <label for="password">Password:</label> 94 - <input type="password" id="password" name="password" class="input"> 95 - 96 - <input type="submit" value="Submit" class="button"> 97 - </form> 98 - </div> 99 - </body> 100 - </html>
-127
cognitivehack/2026/secret-box/app/src/views/my_secrets.ejs
··· 1 - <!DOCTYPE html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8"> 5 - <title>Secrets Vault</title> 6 - <style> 7 - * { 8 - margin: 0; 9 - padding: 0; 10 - box-sizing: border-box; 11 - } 12 - 13 - body { 14 - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 15 - max-width: 1200px; 16 - margin: 0 auto; 17 - padding: 40px 20px; 18 - background-color: #f9f9f9; 19 - color: #2d3436; 20 - line-height: 1.6; 21 - } 22 - 23 - .container { 24 - padding: 40px; 25 - text-align: center; 26 - margin: 0 auto; 27 - } 28 - 29 - .highlight { 30 - font-size: 1.2rem; 31 - margin-bottom: 12px; 32 - font-weight: 600; 33 - } 34 - 35 - .description { 36 - font-size: 1.1rem; 37 - margin-bottom: 36px; 38 - color: #636e72; 39 - } 40 - 41 - .header { 42 - display: flex; 43 - justify-content: space-between; 44 - align-items: center; 45 - margin-bottom: 10px; 46 - padding: 0 5px; 47 - } 48 - 49 - 50 - .buttons { 51 - display: flex; 52 - gap: 15px; 53 - } 54 - 55 - .button { 56 - position: relative; 57 - display: inline-block; 58 - padding: 10px 16px; 59 - text-align: center; 60 - border-radius: 8px; 61 - font-size: 0.85rem; 62 - font-weight: 300; 63 - text-decoration: none; 64 - text-transform: capitalize; 65 - background: #5649c0; 66 - color: white; 67 - min-width: 120px; 68 - } 69 - 70 - .vault-icon { 71 - font-size: 3rem; 72 - margin-bottom: 16px; 73 - } 74 - 75 - 76 - .secret { 77 - background-color: white; 78 - border-radius: 12px; 79 - padding: 20px; 80 - text-align: left; 81 - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); 82 - transition: all 0.3s ease; 83 - border-left: 4px solid #5649c0; 84 - margin: 5px; 85 - } 86 - .secret-date { 87 - color: #939393; 88 - font-size: 0.85rem; 89 - margin-bottom: 10px; 90 - font-style: italic; 91 - } 92 - 93 - .secret-content { 94 - font-size: 1.1rem; 95 - color: #2d3436; 96 - word-break: break-word; 97 - } 98 - </style> 99 - </head> 100 - <body> 101 - <div class="header"> 102 - <div class="vault-icon">🔐</div> 103 - <div class="buttons"> 104 - <a href="/secrets/create" class="button">Create New Secret</a> 105 - <form action="/logout" method="post"> 106 - <button class="button" type="submit">Log out</button> 107 - </form> 108 - </div> 109 - </div> 110 - 111 - <div class="container"> 112 - <div class="highlight">My Secrets</div> 113 - 114 - <% if (secrets && secrets.length > 0) { %> 115 - <% secrets.forEach(sec => { %> 116 - <div class="secret"> 117 - <p> <%= sec.id %></p> 118 - <div class="secret-date"><%= sec.created_at %></div> 119 - <div class="secret-content"><%= sec.content %></div> 120 - </div> 121 - <% }); %> 122 - <% } else { %> 123 - <div class="description"> You don't have any secrets yet.</div> 124 - <% } %> 125 - </div> 126 - </body> 127 - </html>
-100
cognitivehack/2026/secret-box/app/src/views/signup.ejs
··· 1 - <!DOCTYPE html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8"> 5 - <title>Secrets Vault</title> 6 - <style> 7 - * { 8 - margin: 0; 9 - padding: 0; 10 - box-sizing: border-box; 11 - } 12 - 13 - body { 14 - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 15 - max-width: 1200px; 16 - margin: 0 auto; 17 - padding: 40px 20px; 18 - background-color: #f9f9f9; 19 - color: #2d3436; 20 - line-height: 1.6; 21 - } 22 - 23 - .container { 24 - padding: 40px; 25 - text-align: center; 26 - margin: 0 auto; 27 - } 28 - 29 - .description { 30 - font-size: 1.1rem; 31 - margin-bottom: 36px; 32 - color: #636e72; 33 - } 34 - 35 - form { 36 - max-width: 400px; 37 - margin: 0 auto; 38 - padding: 30px; 39 - border-radius: 12px; 40 - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1); 41 - text-align: left; 42 - } 43 - 44 - .input { 45 - width: 100%; 46 - padding: 12px 16px; 47 - margin-bottom: 20px; 48 - border-radius: 8px; 49 - font-size: 1rem; 50 - transition: all 0.3s ease; 51 - } 52 - 53 - .input:focus { 54 - border-color: #5649c0; 55 - box-shadow: 0 0 0 3px rgba(86, 73, 192, 0.2); 56 - } 57 - 58 - .button { 59 - display: block; 60 - width: 100%; 61 - padding: 14px 24px; 62 - text-align: center; 63 - border: none; 64 - border-radius: 8px; 65 - font-size: 1rem; 66 - font-weight: 600; 67 - text-decoration: none; 68 - transition: all 0.3s ease; 69 - text-transform: capitalize; 70 - background: #5649c0; 71 - color: white; 72 - cursor: pointer; 73 - margin-top: 10px; 74 - } 75 - </style> 76 - </head> 77 - <body> 78 - <div class="container"> 79 - <% if (message) { %> 80 - <p style="color: green;"><%= message %></p> 81 - <% } %> 82 - 83 - <% if (error) { %> 84 - <p style="color: red;"><%= error %></p> 85 - <% } %> 86 - 87 - <div class="description">Sign Up</div> 88 - 89 - <form method="POST" action="/signup"> 90 - <label for="username">Name:</label> 91 - <input type="text" id="username" name="username" class="input"> 92 - 93 - <label for="password">Password:</label> 94 - <input type="password" id="password" name="password" class="input"> 95 - 96 - <input type="submit" value="Submit" class="button"> 97 - </form> 98 - </div> 99 - </body> 100 - </html>