sábado, 6 de junio de 2026

OWASP: el top ten en seguridad y vulnerabilidad

En una entrega anterior vimos las 10 vulnerabilidades de seguridad más críticas en aplicaciones web.

La lista OWASP 2025 es la siguiente:

El top ten de las vulnerabilidades web

Número Vulnerabilidad
A01:2025 Broken Access Control
A02:2025 Security Misconfiguration
A03:2025 Software Supply Chain Failures
A04:2025 Cryptographic Failures
A05:2025 Injection
A06:2025 Insecure Design
A07:2025 Authentication Failures
A08:2025 Software or Data Integrity Failures
A09:2025 Security Logging and Alerting Failures
A10:2025 Mishandling of Exceptional Conditions

La tabla del OWASP Top Ten 2025 no es solo un listado teórico: como desarrollador podemos usarla como guía práctica de control de calidad y seguridad en cada etapa del ciclo de vida de tu software.

Ejemplos del OWASP Top Ten

Broken Access Control (A01)

  • Implementa roles y permisos explícitos en tu código (RBAC/ABAC). 
  • Usa pruebas automatizadas para verificar que un usuario no pueda acceder a recursos fuera de su rol. 
  • Ejemplo: en APIs REST, valida siempre el userId contra el token JWT.

Inseguro:

# Cualquiera puede ver datos de otro usuario
user_id = request.args.get("id")
data = db.get_user(user_id)

Seguro:

# Validar que el usuario autenticado coincide
if user_id == current_user.id:
    data = db.get_user(user_id)

Security Misconfiguration (A02)

  • Mantén configuraciones seguras por defecto (no exponer puertos innecesarios, deshabilitar directory listing). 
  • Automatiza revisiones con herramientas como Docker Bench Security o kube-bench en Kubernetes.

Inseguro:

# Exponer listado de directorios
autoindex on;

Seguro:

# Deshabilitar listado
autoindex off;

Software Supply Chain Failures (A03)

  • Usa dependabot o equivalentes para monitorear librerías vulnerables. 
  • Firma y verifica paquetes (ejemplo: npm audit, sigstore). 
  • Evita dependencias sin mantenimiento activo.

Inseguro:

$ npm install paquete-desconocido

Seguro:

$ npm audit
$ npm install paquete-verificado@1.2.3

Cryptographic Failures (A04)

  • Aplica cifrado fuerte (AES‑256, TLS 1.3). 
  • Nunca inventes tu propio algoritmo: usa librerías probadas. 
  • Rotación periódica de claves y certificados.

Inseguro:

# Cifrado débil
cipher = DES.new(key)

Seguro:

# Cifrado fuerte
cipher = AES.new(key, AES.MODE_GCM)

Injection (A05)

  • Usa ORMs o consultas parametrizadas (LINQ, SQL prepared statements). 
  • Escapa entradas en plantillas HTML/JS. 
  • Haz pruebas de fuzzing para detectar inyecciones.

Inseguro:

cursor.execute("SELECT * FROM users WHERE name = '" + name + "'")

Seguro:

cursor.execute("SELECT * FROM users WHERE name = %s", (name,))

Insecure Design (A06)

  • Aplica Threat Modeling desde el inicio (STRIDE, DFD). 
  • Diseña con principios de seguridad por defecto y mínimo privilegio. 
  • Documenta decisiones arquitectónicas con foco en seguridad.

Inseguro:

# Contraseña en texto plano
user.password = "123456"

Seguro:

# Hash seguro
user.password = bcrypt.hashpw(password, bcrypt.gensalt())

Authentication Failures (A07)

  • Implementa MFA (Multi‑Factor Authentication). 
  • Usa protocolos modernos: OAuth2, OpenID Connect
  • Evita sesiones largas sin expiración.

Inseguro:

# Sesión sin expiración
session['user'] = user.id

Seguro:

session['user'] = user.id
session['expires'] = datetime.now() + timedelta(minutes=30)

Software or Data Integrity Failures (A08)

  • Verifica integridad con hashes y firmas digitales. 
  • Usa pipelines CI/CD con validación de integridad. 
  • Protege contra ataques de deserialización insegura.

Inseguro:

# Ejecutar código sin verificar
exec(downloaded_code)

Seguro:

# Verificar firma digital antes de ejecutar
if verify_signature(downloaded_code, signature):
    exec(downloaded_code)

Security Logging and Alerting Failures (A09)

  • Centraliza logs en sistemas como ELK o Azure Monitor. 
  • Define alertas automáticas para eventos críticos (intentos de login fallidos, escalamiento de privilegios). 
  • Asegura que los logs no contengan datos sensibles en texto plano.

Inseguro:

# No se registra intento de login fallido

Seguro:

logger.warning(f"Login fallido para usuario {username}")

Mishandling of Exceptional Conditions (A10)

  • Maneja errores con mensajes genéricos hacia el usuario, pero detallados en logs. 
  • Evita exponer stack traces en producción. 
  • Diseña flujos de fallback seguros (ejemplo: si falla autenticación externa, no dar acceso por defecto).

Inseguro:

# Mostrar error completo al usuario
except Exception as e:
    return str(e)

Seguro:

except Exception as e:
    logger.error(f"Error interno: {e}")
    return "Ha ocurrido un error, inténtalo más tarde."

La tabla del OWASP Top Ten es como nuestro mapa de riesgos más comunes. Si la convertimos en criterios de aceptación en nuestros proyectos, reducimos drásticamente la superficie de ataque.

Enlaces:

https://codemonkeyjunior.blogspot.com/2025/08/owasp-el-top-ten-de-las.html
https://owasp.org/Top10/2025/

LINQ: consultando documentos JSON

En el post anterior vimos cómo realizar consultas en archivos XML. Ahora veremos cómo consultar documentos JSON con LINQ.

Teniendo el siguiente documento JSON:

developer.json

{
  "desarrolladores":[
    {
	"id_empleado":"7894311",
	"nombre": "Karla Alvarez Montoya",
	"telefono": "555 32 53 138",
	"correo":"karla.alvarez@edu.mx"
	},
	{
	"id_empleado":"74533267",
	"nombre": "Laura Torres Jimenez",
	"telefono": "552 99 00 112",
	"correo":"laura.torres@edu.mx"
	},
	{
	"id_empleado":"55533800",
	"nombre": "Joan Sebastian Laredo Arsate",
	"telefono": "553 56 33 008",
	"correo":"joan.laredo.arsate@edu.mx"
	}
  ]
}

1. Vamos a crear un proyecto .NET para consultar ese documento.

$ dotnet new console -n DemoLinqJson
$ cd DemoLinqJson

2. Instalaremos los paquetes necesarios para manipular el docuemnto JSON:

Con la herramienta CLI:

$ dotnet add package Newtonsoft.Json --version 13.0.5-beta1

Con NuGet:

$ NuGet\Install-Package Newtonsoft.Json -Version 13.0.5-beta1

3. Modificamos el programa principal ``Program.cs``:

using System;
using System.Linq;
using Newtonsoft.Json.Linq;

class Program
{
    public static readonly string PATH = "developer.json";
    
    static void Main()
    {
       try{
        var json = File.ReadAllText(PATH);
        var data = JObject.Parse(json);
        Console.WriteLine("Contenido del archivo: {0}",data.ToString());
       } catch (FileNotFoundException ex)
        {
            Console.WriteLine("El archivo no existe: {0}", ex.Message);
        }
    }

}

4. Ejecutamos el proyecto:

$ dotnet run

Salida:

Contenido del archivo: {
  "desarrolladores": [
    {
      "id_empleado": "7894311",
      "nombre": "Karla Alvarez Montoya",
      "telefono": "555 32 53 138",
      "correo": "karla.alvarez@edu.mx"
    },
    {
      "id_empleado": "74533267",
      "nombre": "Laura Torres Jimenez",
      "telefono": "552 99 00 112",
      "correo": "laura.torres@edu.mx"
    },
    {
      "id_empleado": "55533800",
      "nombre": "Joan Sebastian Laredo Arsate",
      "telefono": "553 56 33 008",
      "correo": "joan.laredo.arsate@edu.mx"
    }
  ]
}

Como se puede observar hemos mostrado todo el contenido del archivo JSON. ¿Se podrá realizar consultas? Estamos a punto de averiguarlo.

Lo primero a hacer será crear una clase que contenga la lógica del JSON al leer.

Desarrollador.cs

using System.Text.Json.Serialization;

namespace model
{
    public class Desarrollador
    {
        [JsonPropertyName("id_empleado")]
        public string Id { get; set; } = string.Empty;
        [JsonPropertyName("nombre")]
        public string Nombre { get; set; } = string.Empty;
        [JsonPropertyName("telefono")]
        public string Telefono { get; set; } = string.Empty;
        [JsonPropertyName("correo")]
        public string Correo { get; set; } = string.Empty;
    }

    public class Root
    {
        [JsonPropertyName("desarrolladores")]
        public List<Desarrollador> Desarrolladores { get; set; }
    }
}

Como se puede ver, esta clase es coherente con los atributos del JSON. No solo por el nombre sino por el tipo de dato.

Ahora modifiquemos el programa principal.

Program.cs

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Text.Json;
using model;

class Program
{
    public static readonly string PATH = "developer.json";
    
    static void Main()
    {
        try
        {
            var json = File.ReadAllText(PATH);
            Root data = JsonSerializer.Deserialize<Root>(json);

            Console.WriteLine("Contenido del archivo:");
            foreach (var dev in data.Desarrolladores)
            {
                Console.WriteLine($"{dev.Id} - {dev.Nombre} - {dev.Correo}");
            }

            var desarrolladoresAgrupados = from dev in data.Desarrolladores
                                           group dev by dev.Id into idGroup
                                           select new
                                           {
                                               MyId = idGroup.Key,
                                               Count = idGroup.Count()
                                           };

            foreach (var group in desarrolladoresAgrupados)
            {
                Console.WriteLine($"Id del empleado: {group.MyId}, Count: {group.Count}");
            }
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine("El archivo no existe: {0}", ex.Message);
        }
    }
}

La parte que nos interesa es esta:

            var json = File.ReadAllText(PATH);
            Root data = JsonSerializer.Deserialize<Root>(json);

        
            var desarrolladoresAgrupados = from dev in data.Desarrolladores
                                           group dev by dev.Id into idGroup
                                           select new
                                           {
                                               MyId = idGroup.Key,
                                               Count = idGroup.Count()
                                           };

            foreach (var group in desarrolladoresAgrupados)
            {
                Console.WriteLine($"Id del empleado: {group.MyId}, Count: {group.Count}");
            }

Este bloque lee el contenido del archivo, lo deserializa y posteriormente agrupa a los desarrolladores por su Id y cuenta cuántos hay en cada grupo. Si nos recuerda a una consulta SQL es por que toma referencia a ese lenguaje.

Traducida a una consulta SQL vendría siendo algo como esto:

SELECT 
    id_empleado AS MyId,
    COUNT(*) AS Count
FROM desarrolladores
GROUP BY id_empleado;

Hacer consultas similares a los que se haría en SQL en archivos XML y/o JSON es psible gracias a LINQ.

Hay proyectos en los que no será de mucha ayuda.

Continuaremos en próximas entregas.

Enlaces:

https://www.newtonsoft.com/json/help/html/queryinglinqtojson.htm
https://codemonkeyjunior.blogspot.com/2025/12/linq-consultando-documentos-xml.html
https://medium.com/@ddemirugur/c-13-net-9-part-10-linq-linq-to-xml-json-etc-f6f939f97222
https://developer.mescius.com/blogs/how-to-query-json-in-c-sharp-using-sql-linq-ado-net
https://learn.microsoft.com/es-es/dotnet/standard/linq/
https://www.johnpapa.net/linq-to-json-ndash-checking-for-an-object-or-array/
https://csharphardcoreprogramming.wordpress.com/2016/01/19/json-to-linq-to-json/
https://medium.com/hacking-building/using-linq-to-serialize-a-c-object-into-json-9ecbe9ca2941
https://codesignal.com/learn/courses/parsing-json-with-csharp/lessons/introduction-to-json-and-its-usage-in-csharp

viernes, 22 de mayo de 2026

Lenguajes que han muerto y que no estabas enterado: el caso de Ceylon

Ceylon fue un lenguaje de programación que prometía algo que otros han intentado sin éxito: ser el verdadero sucesor de Java.

Tampoco lo logró.

Fue creado por Gavin King, el mismo creador de Hibernate, y "lanzado" el año 2011.

Digo lanzado, porque las versiones "lanzadas" nunca llegaban a ser estables. Pues cada versión lanzada (valga la redundancia) afectaban al lenguaje y que confundían al pobre ingenuo que se acercaba al lenguaje con el objetivo de aprendera a usarlo.

Lo que aprendías en una versión lo debías desaprender en la nueva... y así sucesivamente.

Actualmente el lenguaje se encuentra archivado por la Fundación Eclipse: https://projects.eclipse.org/projects/technology.ceylon

Ceylon posee (¿debería hablar en presente?) una sintaxis similar a la de Java y C#. Quienes venían de esos lenguajes podían adentrase al lenguaje sin tanto problema.

Características principales:

  • Orientado a objetos. 
  • Soporte a la meta programación. 
  • Imperativo. 
  • De tipado estático. 
  • Soporte la construcción modular. 
  • Multiplataforma.
  • Además de tener su propio IDE (plugin para Eclipse).

Un vistazo a Ceylon

El clásico "Hola, mundo" en Ceylon.

holamundo.ceylon

shared void run(){
    print("Hola, mundo en Ceylon");
}

No mencionaremos cómo compilarlo y ejecutarlo ya que, como mencionamos, cada versión del lenguaje cambiaba todo. Desde cómo comentar código hasta como construir el ejecutable.

Entrevista sobre Ceylon a Gavin King

El tema central de la entrevista fue sobre el nacimiento y propósito del lenguaje Ceylon.

Gavin King comentó que, tras años trabajando con Java, detectó limitaciones en su sistema de módulos y en la coherencia del lenguaje. Ceylon surge para ofrecer una sintaxis más moderna y un modelo de tipos más seguro.

Observemos esta tabla comparativa entre Ceylon y Java.

Comparativa Ceylon y Java

Aspecto Java Ceylon
Origen y creador Desarrollado por Sun Microsystems (1995), liderado por James Gosling. Creado por Gavin King en Red Hat (2011).
Objetivo principal Lenguaje de propósito general para aplicaciones empresariales, móviles y web. Modernizar el ecosistema Java con un lenguaje más coherente, modular y expresivo.
Paradigma Orientado a objetos con soporte funcional desde Java 8. Mixto: orientado a objetos y funcional, con fuerte énfasis en modularidad y claridad semántica.
Tipado Estático y fuerte, pero con inferencia limitada. Estático y fuerte, con inferencia de tipos avanzada y tipos unión/intersección.
Sistema de módulos Introducido en Java 9 (Jigsaw), pero complejo y poco intuitivo. Sistema de módulos nativo desde el inicio, simple y coherente.
Interoperabilidad Corre sobre la JVM y puede interactuar con otros lenguajes del ecosistema. Compila para JVM y JavaScript, permitiendo ejecución en servidor y navegador.
Sintaxis Verbosa y orientada a clases. Más concisa, con sintaxis moderna y expresiva.
Herramientas Ecosistema maduro (IDE, frameworks, librerías). IDE propio con compilador, gestor de módulos y documentación integrada.
Enfoque de diseño Prioriza compatibilidad y estabilidad. Prioriza legibilidad, coherencia y seguridad de tipos.
Casos de uso Aplicaciones empresariales, Android, sistemas financieros. Aplicaciones modulares, APIs, servicios distribuidos y código multiplataforma.

Ceylon representó su intento de modernizar el paradigma Java, ofreciendo una alternativa más elegante y coherente para proyectos grandes y distribuidos. Fue una lástima que no lo haya logrado.

Enlaces:

https://en.wikipedia.org/wiki/Ceylon_(programming_language)
https://swizec.com/blog/cool-thing-thursday-ceylon/
https://codemonkeyjunior.blogspot.com/2012/04/ceylon-funcionando-correctamente.html
https://projects.eclipse.org/projects/technology.ceylon
https://web.mit.edu/ceylon_v1.3.3/ceylon-1.3.3/doc/en/spec/html_single/#:~:text=Ceylon%20is%20a%20general%2Dpurpose,oriented%2C%20and%20higher%2Dorder.


lunes, 18 de mayo de 2026

Comparativa entre MoonBit y Python

MoonBit es un lenguaje de programación relativamente nuevo; un lenguaje orientado a la I.A. Ideal para la computación en la nube y en el borde, que abarca WebAssembly, WebAssembly-GC, JavaScript y backends nativos.

Python es un lenguaje surgido en los 90's; un lenguaje multiparadigma. Cuya filosofía sugiere lo ágil y hace hincapié en la legibilidad del código.

Miremos la siguiente tabla comparativa:

Comparativa MoonBit y Python

Característica Python MoonBit
Creador Guido van Rossum Zhang Hongbo
Paradigma Multiparadigma Programación asíncrona basado en corrutinas, similar a Kotlin
Tipado Dinámico Estático
Extensión .py .mbt
Tipo ejecución Interpretado Compilado
Ideal para REST API, web, etc. Orientado a aplicaciones I.A. y aplicaciones en tiempo real

Ambos lenguajes comparten ciertas características y poseen su propias peculiaridades. No obstante, la mejor forma de comparar estos lenguajes es realizando algunos ejemplos.

Comparando lenguajes de programación

Declaración de variables:

Comparativa MoonBit y Python

Aspecto Python MoonBit
Declaración
x = 10 # todo es asignación dinámica
let x = 10 (inmutable por defecto)
var y = 20 (mutable)
Tipado
# Dinámico, no requiere anotación.
# Ejemplo: 
s = "hola"
# Estático, inferido por el compilador.
# Ejemplo: 
let s: String = "hola"
Tipos básicos
int, float, bool, str, list, dict, tuple, None
Int, Float, Bool, String, Array, Option, Result
Mutabilidad Todas las variables son referencias mutables por defecto Control explícito con let (inmutable) y var (mutable)

Escribamos el clásico programa de "Hola, mundo" en ambos lenguajes.

holamundo.mbt

fn main() {
    print("Hola, mundo")
}

Ejecución:

$ moon run holamundo.mbt

En Python:

holamundo.py

def main():
    print("Hola, mundo")

if __name__ == "__main__":
    main()

Ejecución:

$ python holamundo.py

Miremos otro ejemplo. El clásico programa de "FizzBuzz".

En MoonBit:

fizzbuzz.mbt

fn fizzbuzz(n: Int) {
    for i in 1..n {
        if i % 15 == 0 {
            print("FizzBuzz")
        } else if i % 3 == 0 {
            print("Fizz")
        } else if i % 5 == 0 {
            print("Buzz")
        } else {
            print(i)
        }
    }
}

fn main() {
    fizzbuzz(20)
}

Ejecución:

$ moon run fizzbuzz.mbt

Salida:

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz

En Python:

fizzbuzz.py

def fizzbuzz(n: int):
    for i in range(1, n + 1):
        if i % 15 == 0:
            print("FizzBuzz")
        elif i % 3 == 0:
            print("Fizz")
        elif i % 5 == 0:
            print("Buzz")
        else:
            print(i)

if __name__ == "__main__":
    fizzbuzz(20)

Ejecución:

$ python fizzbuzz.py

Salida:

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz

Creación de proyectos en MoonBit y Python.

Aspecto MoonBit Python
Herramienta oficial moon new <project> crea estructura básica con src/, tests/, moon.mod No hay comando oficial, pero se recomienda estructura estándar con setup.py, requirements.txt, src/, tests/
Estructura típica
├── src/
├── tests/
└── moon.mod
        
├── src/
├── tests/
├── requirements.txt
├── setup.py
└── README.md
        
Gestión de dependencias moon add <package> (usa repositorio oficial) pip install <package> y se registra en requirements.txt
Ejecución moon run python main.py o pytest para pruebas

MoonBit apuesta por tipado estático, mutabilidad controlada y proyectos con estructura mínima pero clara.

Python es dinámico, flexible y tiene una comunidad enorme con convenciones más que reglas estrictas.

Ambos lenguajes tienen similitudes, pero obviamente MoonBit comparte mayor similitud con Go y no tanto con Python.

Python a su vez comparte mayor similitud a lenguajes como Mojo. Un lenguaje que comparte mucha de su sintexis.

Continuaremos más adelante comparando más lenguajes.

Enlaces:

https://codemonkeyjunior.blogspot.com/2026/05/comparativa-entre-go-y-moonbit.html
https://docs.moonbitlang.com/en/latest/tutorial/for-go-programmers/index.html

sábado, 16 de mayo de 2026

Comparativa entre Go y MoonBit

En está ocasión haremos una comparativa entre el lenguaje de programación Go y Moonbit, el lenguaje orientado a I.A.

Go es un lenguaje de programación diseñado para ser rápido, eficiente, concurrente y fácil de aprender. Compilado y con tipado estático, destaca en el desarrollo backend, sistemas en la nube y redes gracias a su gestión automática de memoria y alto rendimiento.

Por el otro lado, MoonBit es una cadena de herramientas de lenguaje de programación nativo de IA para computación en la nube y edge. Además se compila a WebAssembly, JavaScript y C.

Observemos la siguiente tabla comparativa.

Comparativa Go y MoonBit

Característica Go MoonBit
Creador Ken Thompson, Robert Pike y Robert Griesemer Zhang Hongbo
Paradigma Multiparadigma Programación asíncrona basado en corrutinas, similar a Kotlin
Tipado Estático Estático
Extensión .go .mbt
Nivel de abstracción Alto Alto
Tipo de ejecución Compilado Compilado
Ideal para Microservicios, aplicaciones concurrentes, etc. Orientado a la I.A. y aplicaciones en tiempo real

Ambos lenguajes comparten ciertas características y poseen su propias peculiaridades. No obstante, la mejor forma de comparar estos lenguajes es realizando algunos ejemplos.

Para más detalles puedes ver esto: https://docs.moonbitlang.com/en/latest/tutorial/for-go-programmers/index.html


Creando proyectos con Go y MoonBit

Empezaremos creando un sencillo proyecto con Go.

1. Creamos un directorio y nos ubicamos en el:

$ mkdir holamundo
$ cd holamundo

2. Inicializamos el módulo:

$ go mod init example.com\holamundo

3. Creamos un programa ``main.go`` con el siguiente contenido:

package main

import "fmt"

func main() {
  fmt.Println("¡Hola, mundo en Go!")
}

La estructura del proyecto lucirá así:

holamundo/
   go.mod
   main.go

Construimos:

$ go build

Esto creará un ejecutable.

Salida:

¡Hola, mundo en Go!

Ahora con MoonBit.

1. Creamos el proyecto:

$ moon new holamundo
$ cd holamundo

El directorio principal y archivos quedarán de esta forma:

holamundo/
├── cmd
   └── main
       ├── main.mbt
       └── moon.pkg
├── holamundo_test.mbt
├── config.mbt
├── holamundo.mbt
├── moon.mod.json
└── moon.pkg

El contenido del archivo ``main.mbt`` es el siguiente:

fn main {
  println("¡Hola, mundo en MoonBit!")
}

Ahora ejecutamos:

$ moon run cmd\main\main.mbt

Salida:

¡Hola, mundo en MoonBit!

Tomemos un ejercicio de Project Euler: calcular la suma de todos los múltiplos de 3 o 5 menores que 1000.

En Go sería de este modo:

main.go

package main

import  "fmt"

func main() {
    vect := make([]int, 1000)
    for i := 0; i < 1000; i++ {
        vect[i] = i + 1
    }

    sum := 0
    for _, v := range vect {
        if v%3 == 0 && v%5 == 0 {
            sum += v
        }
    }

    fmt.Println("Suma:", sum)
}

Construimos y ejecutamos:

$ go build
$./main.exe

Salida:

Suma: 33165

En MoonBit sería así:

main.mbt

fn main {
    let vect = Array::new()

    for i = 0; i < 1000; i = i + 1 {
        vect.push(i + 1)
    }
    let sum = for i = 0, acc = 0; i < vect.length(); i = i + 1 {
        let v = vect[i]
        if v % 3 == 0 && v % 5 == 0 {
            continue i + 1, acc + v
        }
    } else { acc }

    println("Suma: ")
    println(sum)
}

Por el momento es todo. Continuaremos con la comparativa en próximas entregas.

Enlaces:

https://tour.moonbitlang.com/
https://projecteuler.net/
https://docs.moonbitlang.com/en/latest/tutorial/for-go-programmers/index.html
https://alquimistadecodigo.blogspot.com/search?q=go
https://go.dev/
https://emanuelpeg.blogspot.com/search?q=go

OWASP: el top ten en seguridad y vulnerabilidad

En una entrega anterior vimos las 10 vulnerabilidades de seguridad más críticas en aplicaciones web. La lista OWASP 2025 es la sigu...

Etiquetas

Archivo del blog