eddication
Provides expertise in full-stack development, executive dashboard design, and data analytics using modern technologies and methodologies.
Install this skill
Security score
The eddication skill was audited on Feb 27, 2026 and we found 183 security issues across 6 threat categories. Review the findings below before installing.
Categories Tested
Security Issues
Template literal with variable interpolation in command context
| 122 | .channel(`channel-${userId}`) |
Template literal with variable interpolation in command context
| 127 | filter: `user_id=eq.${userId}` |
Template literal with variable interpolation in command context
| 216 | .channel(`table-${userId}`) |
Template literal with variable interpolation in command context
| 221 | filter: `user_id=eq.${userId}` |
Template literal with variable interpolation in command context
| 365 | ```python |
Template literal with variable interpolation in command context
| 462 | let url = `${this.url}/rest/v1/${table}?select=${select}&limit=${limit}`; |
Template literal with variable interpolation in command context
| 463 | if (filter) url += `&${filter}`; |
Template literal with variable interpolation in command context
| 464 | if (order) url += `&order=${order}`; |
Template literal with variable interpolation in command context
| 469 | 'Authorization': `Bearer ${this.key}`, |
Template literal with variable interpolation in command context
| 476 | throw new Error(`Supabase error: ${response.getContentText()}`); |
Template literal with variable interpolation in command context
| 483 | return UrlFetchApp.fetch(`${this.url}/rest/v1/${table}`, { |
Template literal with variable interpolation in command context
| 487 | 'Authorization': `Bearer ${this.key}`, |
Template literal with variable interpolation in command context
| 879 | id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, |
Template literal with variable interpolation in command context
| 935 | throw new Error(`HTTP ${response.status}`); |
Template literal with variable interpolation in command context
| 1453 | return `${d.getDate()} ${getThaiMonth(d.getMonth() + 1)} ${toBuddhistYear(d.getFullYear())}`; |
Template literal with variable interpolation in command context
| 1556 | return `${cleaned.slice(0, 3)}-${cleaned.slice(3, 6)}-${cleaned.slice(6)}`; |
Template literal with variable interpolation in command context
| 1622 | if (address.houseNumber) parts.push(`${address.houseNumber}`); |
Template literal with variable interpolation in command context
| 1623 | if (address.villageNumber) parts.push(`ม.${address.villageNumber}`); |
Template literal with variable interpolation in command context
| 1626 | if (address.floor) parts.push(`ชั้น ${address.floor}`); |
Template literal with variable interpolation in command context
| 1627 | if (address.room) parts.push(`ห้อง ${address.room}`); |
Template literal with variable interpolation in command context
| 1628 | if (address.alley) parts.push(`ซ.${address.alley}`); |
Template literal with variable interpolation in command context
| 1629 | if (address.road) parts.push(`ถ.${address.road}`); |
Template literal with variable interpolation in command context
| 1632 | if (address.subdistrict) parts.push(`ต.${address.subdistrict}`); |
Template literal with variable interpolation in command context
| 1633 | if (address.district) parts.push(`อ.${address.district}`); |
Template literal with variable interpolation in command context
| 1634 | if (address.province) parts.push(`จ.${address.province}`); |
Template literal with variable interpolation in command context
| 1689 | url.searchParams.set('address', `${address}, Thailand`); |
Template literal with variable interpolation in command context
| 1716 | url.searchParams.set('latlng', `${lat},${lng}`); |
Template literal with variable interpolation in command context
| 1803 | return `${Math.round(meters)} ม.`; |
Template literal with variable interpolation in command context
| 1805 | return `${(meters / 1000).toFixed(1)} กม.`; |
Template literal with variable interpolation in command context
| 2354 | const response = await fetch(`${this.apiBase}/richmenu`, { |
Template literal with variable interpolation in command context
| 2357 | 'Authorization': `Bearer ${this.accessToken}`, |
Template literal with variable interpolation in command context
| 2373 | await fetch(`${this.apiBase}/richmenu/${richMenuId}/content`, { |
Template literal with variable interpolation in command context
| 2376 | 'Authorization': `Bearer ${this.accessToken}`, |
Template literal with variable interpolation in command context
| 2385 | await fetch(`${this.apiBase}/user/${userId}/richmenu/${richMenuId}`, { |
Template literal with variable interpolation in command context
| 2388 | 'Authorization': `Bearer ${this.accessToken}` |
Template literal with variable interpolation in command context
| 2395 | await fetch(`${this.apiBase}/richmenu/${richMenuId}/users`, { |
Template literal with variable interpolation in command context
| 2398 | 'Authorization': `Bearer ${this.accessToken}`, |
Template literal with variable interpolation in command context
| 2407 | await fetch(`${this.apiBase}/richmenu/${richMenuId}`, { |
Template literal with variable interpolation in command context
| 2410 | 'Authorization': `Bearer ${this.accessToken}` |
Template literal with variable interpolation in command context
| 2417 | const response = await fetch(`${this.apiBase}/user/${userId}/richmenu`, { |
Template literal with variable interpolation in command context
| 2419 | 'Authorization': `Bearer ${this.accessToken}` |
Template literal with variable interpolation in command context
| 2431 | await fetch(`${this.apiBase}/user/${userId}/richmenu`, { |
Template literal with variable interpolation in command context
| 2434 | 'Authorization': `Bearer ${this.accessToken}` |
Template literal with variable interpolation in command context
| 2441 | const response = await fetch(`${this.apiBase}/richmenu/list`, { |
Template literal with variable interpolation in command context
| 2443 | 'Authorization': `Bearer ${this.accessToken}` |
Template literal with variable interpolation in command context
| 2543 | altText: `งาน ${job.ref}`, |
Template literal with variable interpolation in command context
| 2552 | text: `งานที่ ${job.ref}`, |
Template literal with variable interpolation in command context
| 2816 | 'Authorization': `Bearer ${this.config.accessToken}`, |
Template literal with variable interpolation in command context
| 2843 | 'Authorization': `Bearer ${this.config.accessToken}` |
Template literal with variable interpolation in command context
| 2860 | 'Authorization': `Bearer ${this.config.accessToken}`, |
Template literal with variable interpolation in command context
| 3063 | const filename = `${user.id}/${Date.now()}-${crypto.randomUUID()}.${ext}`; |
Template literal with variable interpolation in command context
| 3123 | if (cronKey !== `Bearer ${Deno.env.get('CRON_SECRET')}`) { |
Template literal with variable interpolation in command context
| 3149 | const message = ` |
Template literal with variable interpolation in command context
| 3168 | 'Authorization': `Bearer ${LINE_NOTIFY_TOKEN}`, |
Template literal with variable interpolation in command context
| 3208 | super(`${resource} not found`, 404, 'NOT_FOUND'); |
Template literal with variable interpolation in command context
| 3359 | return { error: `${firstError.path.join('.')}: ${firstError.message}` }; |
Template literal with variable interpolation in command context
| 3561 | error: rules.message || `Minimum ${rules.minLength} characters required` |
Template literal with variable interpolation in command context
| 3569 | error: rules.message || `Maximum ${rules.maxLength} characters allowed` |
Template literal with variable interpolation in command context
| 3937 | document.documentElement.style.setProperty('--viewport-width', `${info.width}px`); |
Template literal with variable interpolation in command context
| 3938 | document.documentElement.style.setProperty('--viewport-height', `${info.height}px`); |
Template literal with variable interpolation in command context
| 3939 | document.documentElement.style.setProperty('--safe-top', `${insets.top}px`); |
Template literal with variable interpolation in command context
| 3940 | document.documentElement.style.setProperty('--safe-bottom', `${insets.bottom}px`); |
Template literal with variable interpolation in command context
| 4403 | html: `ข้อมูลของคุณ: <pre>${JSON.stringify(result.value)}</pre>`, |
Template literal with variable interpolation in command context
| 4500 | html: ` |
Template literal with variable interpolation in command context
| 4578 | html: ` |
Template literal with variable interpolation in command context
| 4837 | <div className={`bg-white rounded-lg border border-gray-100 ${sizeClasses[size]} shadow-sm`}> |
Template literal with variable interpolation in command context
| 4851 | <div className={`font-bold text-gray-800 ${valueSizeClasses[size]} tracking-tight mb-1`}> |
Template literal with variable interpolation in command context
| 4861 | <span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium ${trendColors[trend]}`}> |
Template literal with variable interpolation in command context
| 4923 | className={`p-5 rounded-lg border ${statusColors[item.status]}`} |
Template literal with variable interpolation in command context
| 5043 | return `${context.parsed.y.toLocaleString('th-TH')}`; |
Template literal with variable interpolation in command context
| 5136 | return `${context.label}: ${value.toLocaleString('th-TH')} (${percentage}%)`; |
Template literal with variable interpolation in command context
| 5171 | header.innerHTML = ` |
Template literal with variable interpolation in command context
| 5199 | const trendHtml = options.change !== undefined ? ` |
Template literal with variable interpolation in command context
| 5210 | card.innerHTML = ` |
Template literal with variable interpolation in command context
| 5225 | section.innerHTML = ` |
Template literal with variable interpolation in command context
| 5326 | return `<span class="${bg} ${text} px-3 py-1 rounded-full text-xs font-medium inline-flex items-center gap-2"> |
Template literal with variable interpolation in command context
| 5729 | query = query.like(filter.field, `%${filter.value}%`); |
Template literal with variable interpolation in command context
| 5851 | const filename = `${options.filename}_${timestamp}.${options.format}`; |
Template literal with variable interpolation in command context
| 5924 | printWindow.document.write(` |
Template literal with variable interpolation in command context
| 5932 | @page { ${options.orientation ? `size: A4 ${options.orientation};` : ''} } |
Template literal with variable interpolation in command context
| 5966 | const html = ` |
Template literal with variable interpolation in command context
| 6047 | title: `ใบรับงาน ${job.ref}`, |
Template literal with variable interpolation in command context
| 6087 | id ? `${resource} with id ${id} not found` : `${resource} not found`, |
Template literal with variable interpolation in command context
| 6274 | `%c[${entry.level.toUpperCase()}] ${entry.message}`, |
Template literal with variable interpolation in command context
| 6505 | const url = new URL(`${SUPABASE_URL}/storage/v1/object/public/${STORAGE_BUCKET}/${path}`); |
Template literal with variable interpolation in command context
| 6533 | .map(size => `${getOptimizedImageUrl(path, { width: size, quality })} ${size}w`) |
Template literal with variable interpolation in command context
| 6644 | if (document.querySelector(`script[src="${src}"]`)) { |
Template literal with variable interpolation in command context
| 6655 | script.onerror = () => reject(new Error(`Failed to load script: ${src}`)); |
Template literal with variable interpolation in command context
| 6739 | email: `test-${Date.now()}@example.com`, |
Template literal with variable interpolation in command context
| 6759 | ref: `TEST-${Date.now()}`, |
Template literal with variable interpolation in command context
| 6909 | job: (id: string) => `/api/v1/jobs/${id}`, |
Template literal with variable interpolation in command context
| 6910 | jobStops: (id: string) => `/api/v1/jobs/${id}/stops`, |
Template literal with variable interpolation in command context
| 6911 | jobCheckin: (id: string) => `/api/v1/jobs/${id}/checkin`, |
Template literal with variable interpolation in command context
| 6912 | jobCheckout: (id: string) => `/api/v1/jobs/${id}/checkout`, |
Template literal with variable interpolation in command context
| 6916 | driver: (id: string) => `/api/v1/drivers/${id}`, |
Template literal with variable interpolation in command context
| 6917 | driverStatus: (id: string) => `/api/v1/drivers/${id}/status`, |
Template literal with variable interpolation in command context
| 6918 | driverLocation: (id: string) => `/api/v1/drivers/${id}/location`, |
Template literal with variable interpolation in command context
| 6922 | station: (id: string) => `/api/v1/stations/${id}`, |
Template literal with variable interpolation in command context
| 6926 | driverReport: (id: string, period: string) => `/api/v1/reports/drivers/${id}/${period}` |
Template literal with variable interpolation in command context
| 6985 | notFound: (resource: string) => errorResponse(`${resource} not found`, 'NOT_FOUND', 404), |
Template literal with variable interpolation in command context
| 7016 | const url = `${this.config.baseUrl}${endpoint}`; |
Template literal with variable interpolation in command context
| 7027 | headers['Authorization'] = `Bearer ${token}`; |
Template literal with variable interpolation in command context
| 7179 | console.group(`Action: ${action.type}`); |
Template literal with variable interpolation in command context
| 7337 | return `${token}.${signature}`; |
Template literal with variable interpolation in command context
| 7411 | headers.set('Strict-Transport-Security', `max-age=${maxAge}${includeSub ? '; includeSubDomains' : ''}`); |
Template literal with variable interpolation in command context
| 7420 | .map(([directive, value]) => `${directive} ${value}`) |
Template literal with variable interpolation in command context
| 7569 | ```yaml |
Template literal with variable interpolation in command context
| 7647 | ```yaml |
Template literal with variable interpolation in command context
| 7737 | console.log(`${c.name.padEnd(25)} [${c.status.toUpperCase()}]`); |
Template literal with variable interpolation in command context
| 7738 | console.log(` ${c.message}`); |
Template literal with variable interpolation in command context
| 7965 | const filename = `signatures/${jobId}/${Date.now()}.png`; |
Template literal with variable interpolation in command context
| 8022 | throw new Error(`Element ${elementId} not found`); |
Template literal with variable interpolation in command context
| 8067 | return `${baseUrl}/job/${jobRef}`; |
Template literal with variable interpolation in command context
| 8175 | throw new Error(`Element ${elementId} not found`); |
Fetch to external URL
| 3165 | await fetch('https://notify-api.line.me/api/notify', { |
Webhook reference - potential data exfiltration
| 22 | | **APIs & Integration** | LINE Platform, REST APIs, Webhooks, OAuth, Third-party integrations | |
Webhook reference - potential data exfiltration
| 320 | // Webhook signature verification |
Webhook reference - potential data exfiltration
| 332 | // Express webhook handler |
Webhook reference - potential data exfiltration
| 337 | app.post('/webhook', |
Webhook reference - potential data exfiltration
| 6771 | ### Mock Webhook Testing |
Webhook reference - potential data exfiltration
| 6774 | // tests/mocks/line-webhook.ts |
Webhook reference - potential data exfiltration
| 6776 | * Mock LINE webhook for testing |
Webhook reference - potential data exfiltration
| 6779 | export interface MockWebhookEvent { |
Webhook reference - potential data exfiltration
| 6787 | export function createMockWebhook(events: MockWebhookEvent[]): { |
Webhook reference - potential data exfiltration
| 6799 | // Mock webhook request |
Webhook reference - potential data exfiltration
| 6800 | export function mockWebhookRequest(events: MockWebhookEvent[]): Request { |
Webhook reference - potential data exfiltration
| 6801 | const { body, signature } = createMockWebhook(events); |
Webhook reference - potential data exfiltration
| 6803 | return new Request('https://example.com/webhook/line', { |
Access to .env file
| 245 | const LIFF_ID = import.meta.env.VITE_LIFF_ID; |
Access to .env file
| 341 | if (!verifyLineSignature(req.body.toString(), signature, process.env.LINE_CHANNEL_SECRET!)) { |
Access to .env file
| 709 | Deno.env.get('SUPABASE_URL')!, |
Access to .env file
| 710 | Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! |
Access to .env file
| 2897 | const supabaseUrl = Deno.env.get('SUPABASE_URL')!; |
Access to .env file
| 2898 | const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; |
Access to .env file
| 3000 | const supabaseUrl = Deno.env.get('SUPABASE_URL')!; |
Access to .env file
| 3001 | const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; |
Access to .env file
| 3116 | const supabaseUrl = Deno.env.get('SUPABASE_URL')!; |
Access to .env file
| 3117 | const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; |
Access to .env file
| 3118 | const LINE_NOTIFY_TOKEN = Deno.env.get('LINE_NOTIFY_TOKEN')!; |
Access to .env file
| 3123 | if (cronKey !== `Bearer ${Deno.env.get('CRON_SECRET')}`) { |
Access to .env file
| 6266 | if (import.meta.env.DEV) { |
Access to .env file
| 6731 | const testSupabaseUrl = process.env.SUPABASE_TEST_URL!; |
Access to .env file
| 6732 | const testSupabaseKey = process.env.SUPABASE_TEST_ANON_KEY!; |
Access to .env file
| 7710 | process.env.DATABASE_URL && process.env.SUPABASE_URL, |
Prompting for password/secret input
| 543 | await page.fill('[data-testid="password-input"]', 'password123'); |
Prompting for password/secret input
| 4266 | // Password input |
Base64 decode via atob()
| 4005 | const rawData = window.atob(base64); |
Hex-encoded characters
| 7498 | return unsafe.replace(/[\0\x08\x09\x1a\n\r"'\\\%]/g, char => { |
Hex-encoded characters
| 7501 | case '\x08': return '\\b'; |
Hex-encoded characters
| 7502 | case '\x09': return '\\t'; |
Hex-encoded characters
| 7503 | case '\x1a': return '\\z'; |
External URL reference
| 383 | allow_origins=os.getenv("ALLOWED_ORIGINS", "http://localhost:3000").split(","), |
External URL reference
| 702 | import { serve } from 'https://deno.land/[email protected]/http/server.ts'; |
External URL reference
| 703 | import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; |
External URL reference
| 1688 | const url = new URL('https://maps.googleapis.com/maps/api/geocode/json'); |
External URL reference
| 1715 | const url = new URL('https://maps.googleapis.com/maps/api/geocode/json'); |
External URL reference
| 2331 | private apiBase = 'https://api.line.me/v2/bot' |
External URL reference
| 2802 | const LINE_NOTIFY_API = 'https://notify-api.line.me/api/notify'; |
External URL reference
| 2894 | import { serve } from 'https://deno.land/[email protected]/http/server.ts'; |
External URL reference
| 2895 | import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; |
External URL reference
| 2997 | import { serve } from 'https://deno.land/[email protected]/http/server.ts'; |
External URL reference
| 2998 | import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; |
External URL reference
| 3113 | import { serve } from 'https://deno.land/[email protected]/http/server.ts'; |
External URL reference
| 3114 | import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; |
External URL reference
| 3165 | await fetch('https://notify-api.line.me/api/notify', { |
External URL reference
| 3289 | import { z } from 'https://deno.land/x/zod/mod.ts'; |
External URL reference
| 4033 | <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> |
External URL reference
| 5343 | <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;600;700&family=Noto+Sans+Thai:wght@400;500;600;700&display=swap" rel="stylesheet"> |
External URL reference
| 5947 | <link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@400;700&display=swap" rel="stylesheet"> |
External URL reference
| 6172 | import * as Sentry from 'https://deno.land/x/[email protected]/index.ts'; |
External URL reference
| 6803 | return new Request('https://example.com/webhook/line', { |
External URL reference
| 7998 | * Load from: https://cdn.jsdelivr.net/npm/[email protected]/qrcode.min.js |
External URL reference
| 8077 | * Load from: https://unpkg.com/html5-qrcode |
External URL reference
| 8149 | * Using JsBarcode library: https://cdn.jsdelivr.net/npm/[email protected]/dist/JsBarcode.all.min.js |
External URL reference
| 8246 | | **Supabase** | https://supabase.com/docs | |
External URL reference
| 8247 | | **PostgreSQL** | https://www.postgresql.org/docs/ | |
External URL reference
| 8248 | | **LINE Platform** | https://developers.line.biz/ | |
External URL reference
| 8249 | | **React** | https://react.dev | |
External URL reference
| 8250 | | **TypeScript** | https://www.typescriptlang.org/docs | |
External URL reference
| 8251 | | **Vue** | https://vuejs.org | |
External URL reference
| 8252 | | **FastAPI** | https://fastapi.tiangolo.com | |
External URL reference
| 8254 | | **Playwright** | https://playwright.dev | |
External URL reference
| 8255 | | **Google Apps Script** | https://developers.google.com/apps-script | |