<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ethicals7s</title>
    <description>The latest articles on DEV Community by ethicals7s (@ethicals7s).</description>
    <link>https://dev.to/ethicals7s</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3644522%2F24a078d0-75c2-4a91-a2be-cf576a27867e.png</url>
      <title>DEV Community: ethicals7s</title>
      <link>https://dev.to/ethicals7s</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ethicals7s"/>
    <language>en</language>
    <item>
      <title>I Built an EPSS-Integrated CVE Risk Scoring Tool (Day0Predictor v0.1)</title>
      <dc:creator>ethicals7s</dc:creator>
      <pubDate>Fri, 12 Dec 2025 18:58:33 +0000</pubDate>
      <link>https://dev.to/ethicals7s/i-built-an-epss-integrated-cve-risk-scoring-tool-day0predictor-v01-4jd6</link>
      <guid>https://dev.to/ethicals7s/i-built-an-epss-integrated-cve-risk-scoring-tool-day0predictor-v01-4jd6</guid>
      <description>&lt;p&gt;Security teams don’t have a CVE problem — they have a prioritization problem.&lt;/p&gt;

&lt;p&gt;CVSS tells us severity.&lt;br&gt;
EPSS tells us likelihood of exploitation.&lt;/p&gt;

&lt;p&gt;But defenders still end up asking:&lt;/p&gt;

&lt;p&gt;“Which CVEs do I actually fix first?”&lt;/p&gt;

&lt;p&gt;To explore that gap, I built Day0Predictor v0.1 — a defensive, transparent CVE risk scoring tool that integrates EPSS signals with interpretable machine learning.&lt;/p&gt;

&lt;p&gt;This is not a zero-day detector and not a scanner.&lt;br&gt;
It’s a prioritization signal designed to be auditable and explainable.&lt;/p&gt;

&lt;p&gt;🔍 What Day0Predictor Does&lt;/p&gt;

&lt;p&gt;Combines EPSS score + percentile&lt;/p&gt;

&lt;p&gt;Adds structured threshold features (≥0.01, ≥0.10, ≥0.50)&lt;/p&gt;

&lt;p&gt;Trains a lightweight, interpretable model&lt;/p&gt;

&lt;p&gt;Outputs:&lt;/p&gt;

&lt;p&gt;Risk score (0–100)&lt;/p&gt;

&lt;p&gt;Features used&lt;/p&gt;

&lt;p&gt;Reasons for the score&lt;/p&gt;

&lt;p&gt;Clear disclaimers&lt;/p&gt;

&lt;p&gt;No black box. No hype.&lt;/p&gt;

&lt;p&gt;🧠 Why EPSS Alone Isn’t Enough&lt;/p&gt;

&lt;p&gt;EPSS is powerful, but in practice:&lt;/p&gt;

&lt;p&gt;Scores fluctuate daily&lt;/p&gt;

&lt;p&gt;Context is missing (attack patterns, structure)&lt;/p&gt;

&lt;p&gt;Defenders still need explanation&lt;/p&gt;

&lt;p&gt;Day0Predictor treats EPSS as strong evidence, not truth.&lt;/p&gt;

&lt;p&gt;Think of it as:&lt;/p&gt;

&lt;p&gt;EPSS + structure + explainability&lt;/p&gt;

&lt;p&gt;🧪 Example Output&lt;br&gt;
{&lt;br&gt;
  "cve_id": "CVE-2021-44228",&lt;br&gt;
  "risk": 98,&lt;br&gt;
  "mode": "trained_model_epss",&lt;br&gt;
  "features": {&lt;br&gt;
    "epss": 0.94358,&lt;br&gt;
    "percentile": 0.99957,&lt;br&gt;
    "epss_ge_050": 1.0&lt;br&gt;
  },&lt;br&gt;
  "reasons": [&lt;br&gt;
    { "feature": "epss", "direction": "up" },&lt;br&gt;
    { "feature": "percentile", "direction": "up" }&lt;br&gt;
  ]&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This is the kind of output defenders can audit and trust.&lt;/p&gt;

&lt;p&gt;🛠️ CLI Usage&lt;/p&gt;

&lt;p&gt;Score a CVE directly by ID using EPSS:&lt;/p&gt;

&lt;p&gt;day0predict score-epss \&lt;br&gt;
  --cve-id CVE-2021-44228 \&lt;br&gt;
  --model models/day0predict.joblib \&lt;br&gt;
  --format json&lt;/p&gt;

&lt;p&gt;You can also score CVE JSON files directly.&lt;/p&gt;

&lt;p&gt;📊 Model Notes&lt;/p&gt;

&lt;p&gt;Logistic regression (intentionally simple)&lt;/p&gt;

&lt;p&gt;Handles class imbalance&lt;/p&gt;

&lt;p&gt;ROC-AUC ≈ 0.92&lt;/p&gt;

&lt;p&gt;Explainability prioritized over complexity&lt;/p&gt;

&lt;p&gt;This tool is meant to support human judgment, not replace it.&lt;/p&gt;

&lt;p&gt;📦 Open Source&lt;/p&gt;

&lt;p&gt;GitHub:&lt;br&gt;
👉 [&lt;a href="https://github.com/ethicals7s/day0predictor-v0.1" rel="noopener noreferrer"&gt;https://github.com/ethicals7s/day0predictor-v0.1&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://github.com/ethicals7s/day0predictor-v0.1" rel="noopener noreferrer"&gt;https://github.com/ethicals7s/day0predictor-v0.1&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;MIT licensed. Feedback and PRs welcome.&lt;/p&gt;

&lt;p&gt;🔮 What’s Next&lt;/p&gt;

&lt;p&gt;Ideas for v0.2:&lt;/p&gt;

&lt;p&gt;Time-aware training (train on past → predict future)&lt;/p&gt;

&lt;p&gt;Explicit CISA KEV features&lt;/p&gt;

&lt;p&gt;Lightweight web demo&lt;/p&gt;

&lt;p&gt;Expanded text feature analysis&lt;/p&gt;

&lt;p&gt;🧠 Final Thought&lt;/p&gt;

&lt;p&gt;Security doesn’t need more hype tools.&lt;/p&gt;

&lt;p&gt;It needs boring, honest, defensible signals that help humans decide what matters now.&lt;/p&gt;

&lt;p&gt;That’s what I tried to build with Day0Predictor.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgfg1ztfnej2id4qnp5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgfg1ztfnej2id4qnp5z.png" alt=" " width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>tooling</category>
      <category>showdev</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>My First Ethical Open Redirect Scanner: From Zero to Shipped</title>
      <dc:creator>ethicals7s</dc:creator>
      <pubDate>Sun, 07 Dec 2025 01:39:01 +0000</pubDate>
      <link>https://dev.to/ethicals7s/my-first-ethical-open-redirect-scanner-from-zero-to-shipped-4h69</link>
      <guid>https://dev.to/ethicals7s/my-first-ethical-open-redirect-scanner-from-zero-to-shipped-4h69</guid>
      <description>&lt;p&gt;Hey dev community! I'm ethicals7s, a self-taught hacker grinding from zero—no mentors, just raw determination after losing my parents young. In a few intense days, I designed, coded, and shipped my first ethical open redirect vulnerability scanner in Node.js. This tool isn't just basic—it's optimized with async parallel scans, rate limiting for responsible testing, and JSON export for pro-level logging, making it faster and more robust than my earlier Python attempts. Here's the full breakdown: my journey, the tech behind it, and how you can dive in.&lt;br&gt;
The Journey&lt;/p&gt;

&lt;p&gt;As someone building my way up in tech, I wanted a tool to automate bug bounty hunts for open redirects—those sneaky params that can lead to phishing or worse. I started with research on OWASP guidelines, sketched the logic (payload injection, HTTP status checks), and coded it step by step. Debugging async issues and adding ethics (like delays to avoid DoS) was the real grind, but it taught me tons about full-stack security. This is my unconventional route to senior-level skills—turning challenges into code that matters.&lt;br&gt;
Features&lt;/p&gt;

&lt;p&gt;Batch testing: Reads URLs from a text file for efficient scans.&lt;br&gt;
Payload injection: Appends ?redirect=&lt;a href="https://evil.com" rel="noopener noreferrer"&gt;https://evil.com&lt;/a&gt; to detect vulnerable redirects.&lt;br&gt;
Async parallelism: Uses Promise.all for simultaneous checks—blazing fast on multiple URLs.&lt;br&gt;
Rate limiting: Built-in 1-second delay per scan to prevent abuse and stay ethical.&lt;br&gt;
JSON export: Saves results as structured data for analysis or reports.&lt;br&gt;
Ethical focus: Designed for permitted testing only, with safe examples and warnings.&lt;/p&gt;

&lt;p&gt;Install&lt;br&gt;
Get the dependencies with npm:&lt;br&gt;
npm install axios yargs&lt;/p&gt;

&lt;p&gt;Usage&lt;/p&gt;

&lt;p&gt;Create urls.txt with one URL per line (safe tests only—e.g., known redirect mimics):texthttps://&lt;a href="http://www.google.com/url?q=https://evil.com" rel="noopener noreferrer"&gt;www.google.com/url?q=https://evil.com&lt;/a&gt;&lt;br&gt;
&lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.koni-store.ru/bitrix/redirect.php?event1=&amp;amp;event2=&amp;amp;event3=&amp;amp;goto=https://google.com" rel="noopener noreferrer"&gt;https://www.koni-store.ru/bitrix/redirect.php?event1=&amp;amp;event2=&amp;amp;event3=&amp;amp;goto=https://google.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the scanner:node index.js scan&lt;/p&gt;

&lt;p&gt;Example Output&lt;/p&gt;

&lt;p&gt;Scanning for open redirects (ethical tests only)...&lt;br&gt;
&lt;a href="https://www.google.com/url?q=https://evil.com" rel="noopener noreferrer"&gt;https://www.google.com/url?q=https://evil.com&lt;/a&gt; is VULNERABLE.&lt;br&gt;
&lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt; is SAFE.&lt;br&gt;
&lt;a href="https://www.koni-store.ru/bitrix/redirect.php?event1=&amp;amp;event2=&amp;amp;event3=&amp;amp;goto=https://google.com" rel="noopener noreferrer"&gt;https://www.koni-store.ru/bitrix/redirect.php?event1=&amp;amp;event2=&amp;amp;event3=&amp;amp;goto=https://google.com&lt;/a&gt; is VULNERABLE.&lt;/p&gt;

&lt;p&gt;results.json (auto-generated):&lt;br&gt;
text[&lt;br&gt;
  {&lt;br&gt;
    "url": "&lt;a href="https://www.google.com/url?q=https://evil.com" rel="noopener noreferrer"&gt;https://www.google.com/url?q=https://evil.com&lt;/a&gt;",&lt;br&gt;
    "status": "VULNERABLE"&lt;br&gt;
  },&lt;br&gt;
  {&lt;br&gt;
    "url": "&lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;",&lt;br&gt;
    "status": "SAFE"&lt;br&gt;
  },&lt;br&gt;
  {&lt;br&gt;
    "url": "&lt;a href="https://www.koni-store.ru/bitrix/redirect.php?event1=&amp;amp;event2=&amp;amp;event3=&amp;amp;goto=https://google.com" rel="noopener noreferrer"&gt;https://www.koni-store.ru/bitrix/redirect.php?event1=&amp;amp;event2=&amp;amp;event3=&amp;amp;goto=https://google.com&lt;/a&gt;",&lt;br&gt;
    "status": "VULNERABLE"&lt;br&gt;
  }&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;Code Snippet (index.js)&lt;br&gt;
Here's the core—clean, efficient, and ready to fork:&lt;br&gt;
JavaScriptconst fs = require('fs');&lt;br&gt;
const axios = require('axios');&lt;br&gt;
const path = require('path');&lt;br&gt;
const yargs = require('yargs');&lt;/p&gt;

&lt;p&gt;const MALICIOUS_DOMAIN = 'evil.com';&lt;br&gt;
const INPUT_FILE = path.join(__dirname, 'urls.txt');&lt;/p&gt;

&lt;p&gt;async function checkForOpenRedirect(url) {&lt;br&gt;
  try {&lt;br&gt;
    const testUrl = &lt;code&gt;${url}?redirect=https://${MALICIOUS_DOMAIN}&lt;/code&gt;;&lt;br&gt;
    const response = await axios.get(testUrl, { maxRedirects: 0, validateStatus: null });&lt;br&gt;
    if (response.status &amp;gt; 300 &amp;amp;&amp;amp; response.status &amp;lt; 400) {&lt;br&gt;
      const location = response.headers.location;&lt;br&gt;
      if (location &amp;amp;&amp;amp; location.includes(MALICIOUS_DOMAIN)) {&lt;br&gt;
        return true;&lt;br&gt;
      }&lt;br&gt;
    }&lt;br&gt;
    return false;&lt;br&gt;
  } catch (error) {&lt;br&gt;
    console.error(&lt;code&gt;Error checking ${url}: ${error.message}&lt;/code&gt;);&lt;br&gt;
    return false;&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;async function main(file = INPUT_FILE) {&lt;br&gt;
  if (!fs.existsSync(file)) {&lt;br&gt;
    console.error(&lt;code&gt;Input file not found: ${file}&lt;/code&gt;);&lt;br&gt;
    console.log('Please create a urls.txt file with one URL per line. Use safe tests only.');&lt;br&gt;
    return;&lt;br&gt;
  }&lt;br&gt;
  const urls = fs.readFileSync(file, 'utf-8').split('\n').filter(Boolean);&lt;br&gt;
  console.log('Scanning for open redirects (ethical tests only)...');&lt;br&gt;
  const results = await Promise.all(urls.map(async (url) =&amp;gt; {&lt;br&gt;
    const vulnerable = await checkForOpenRedirect(url);&lt;br&gt;
    await new Promise(resolve =&amp;gt; setTimeout(resolve, 1000)); // Rate limit&lt;br&gt;
    return { url, status: vulnerable ? 'VULNERABLE' : 'SAFE' };&lt;br&gt;
  }));&lt;br&gt;
  results.forEach(({ url, status }) =&amp;gt; console.log(&lt;code&gt;${url} is ${status}.&lt;/code&gt;));&lt;br&gt;
  fs.writeFileSync('results.json', JSON.stringify(results, null, 2)); // JSON export&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;// CLI&lt;br&gt;
yargs.command('scan', 'Scan for open redirects', {&lt;br&gt;
  file: { description: 'Input file', alias: 'f', type: 'string', default: 'urls.txt' }&lt;br&gt;
}, (argv) =&amp;gt; main(argv.file))&lt;br&gt;
  .help()&lt;br&gt;
  .argv;&lt;br&gt;
Notes&lt;/p&gt;

&lt;p&gt;Ethical Use Only: Permission-based testing only. Inspired by bug bounties—report responsibly. No production scans without consent.&lt;br&gt;
License: MIT—fork it on GitHub: &lt;a href="https://github.com/ethicals7s/ethicals7s-redirect-hunter" rel="noopener noreferrer"&gt;https://github.com/ethicals7s/ethicals7s-redirect-hunter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What do you think? Fork, test, or suggest improvements—let's collab! Next: Fraud detector or cert grind. Feedback welcome!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>security</category>
      <category>node</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
